diff --git a/packages/cactus-plugin-bungee/README.md b/packages/cactus-plugin-bungee/README.md new file mode 100644 index 00000000000..c96f67c3b3d --- /dev/null +++ b/packages/cactus-plugin-bungee/README.md @@ -0,0 +1,159 @@ +# `@hyperledger/cactus-plugin-bungee` + + The package provides `Hyperledger Cacti` a way to create blockchain snapshots and views, for different distributed ledgers currently supported by Cacti. The implementation follows the paper BUNGEE(https://dl.acm.org/doi/pdf/10.1145/3643689) + +## Summary + +- [`@hyperledger/cactus-plugin-bungee`](#hyperledgercactus-plugin-bungee) + - [Summary](#summary) + - [Getting Started](#getting-started) + - [Prerequisites](#prerequisites) + - [Architecture](#architecture) + - [BUNGEE API](#bungee-api) + - [Running the tests](#running-the-tests) + - [Usage](#usage) + - [Contributing](#contributing) + - [License](#license) + + +## Getting Started + +Clone the git repository on your local machine. Follow these instructions that will get you a copy of the project up and running on +your local machine for development and testing purposes. + +### Prerequisites + +In the root of the project to install the dependencies execute the command: +```sh +npm run configure +``` + +Know how to use the following plugins of the project: + + - [cactus-plugin-ledger-connector-fabric](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-fabric) + - [cactus-plugin-ledger-connector-besu](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-besu) + +Note that at the moment, only logic for Fabric and Besu networks + +## Architecture + +BUNGEE is a blockchain view generator, serving multiple purposes such as stakeholder-centric snapshots for audits, cross-chain analysis, blockchain migration, and combined on-chain-off-chain analytics. + +The plugin interacts with a cactus ledger connector, using strategies with custom logic for each different network. + +Note that, so far, only strategies for Fabric and Besu networks were implemented. + +The plugin stands _behind_ a cacti-ledger-connector, which is used to fetch information from the ledger to create the snapshot. + +....................................... +. Cacti Node . +. . +. . +. .......... ............. . ......... +. . . . Cacti . . . . +. . BUNGEE . ---------- . Connector . -----------. DLT . +. . . ............. . . . +. .......... . ......... +. . +. . +. . +....................................... + +The plugin can then serve multiple purposes, and thus serve also other plugins or apps in more complex deployment architectures (where we link bungee to other components). + +### BUNGEE API + +This plugin uses OpenAPI to generate the API paths. +Endpoints exposed: + + - CreateViewV1 + + +## Running the tests + - **besu-test-basic.test.ts**: A test using strategy-besu and a besu connector, testing creating views for different timeframes and states. + - **fabric-test-basic.test.ts**: A test using strategy-fabric and a fabric connector, testing creating views for different timeframes and states. + - **besu-test-pruning.test.ts**: A test using strategy-besu and a besu connector, testing creating views for specific timeframes. + - **fabric-test-pruning.test.ts**: A test using strategy-fabric and a fabric connector, testing creating views for specific timeframes. + - **bungee-api-test.test.ts**: A more complex test, using both besu and fabric strategies, fabric and besu connectors, and calls to bungee API. Tests bungee's API and functionality with multiple strategies. + + +## Usage +Lets imagine we want bungee to create views for a besu ledger. +Let us consider a besu ledger connector, exposing its API on URL: http://localhost:4000 + + +Then we instantiate the plugin as follows: +```typescript +const pluginBungeeOptions = { + keyPair: Secp256k1Keys.generateKeyPairsBuffer(), + instanceId: uuidv4(), + logLevel, +}; +const bungee = new PluginBUNGEE(pluginBungeeOptions); +``` + +We add the desired strategies: + +```typescript +bungee.addStrategy('BESU_STRATEGY', new StrategyBesu("INFO")); +``` + +Save network details for our target ledger: + +```typescript +const besuNetworkDetails: BesuNetworkDetails = { + signingCredential: besuSigningCredential, + contractName: besuContractName, + connectorApiPath: 'http://localhost:4000', + keychainId: besuKeychainPlugin.getKeychainId(), + contractAddress: besuContractAddress, + participant: accountAddress, + }; +``` + +And we can request views, after exposing the api: +```typescript +const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + bungeeServer = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 3000, + server: bungeeServer, + }; +const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; +const { address, port } = addressInfo; + +await bungee.getOrCreateWebServices(); +await bungee.registerWebServices(expressApp); +const bungeePath = `http://${address}:${port}`; + +const config = new Configuration({ basePath: bungeePath }); +const bungeeApi = new BungeeApi(config); + +const viewBesu = await bungeeApi.createViewV1({ + strategyId: 'BESU_STRATEGY', + networkDetails: besuNetworkDetails, + tI: undefined, //default to 0 + tF: undefined, //default to 9999999999999 + stateIds: undefined, //default to capture all assets + viewID: undefined, //plugin generates the id, if not given + } as CreateViewRequest); +``` + +Note that each strategy can be used to query different ledgers (ledgers of the same type, but on different locations), and BUNGEE also supports adding multiple strategies to each bungee-plugin instance. +Each strategy implements the logic to query information from each different ledger (i.e. capture set of asset states), while bungee plugin handles the snapshot and view creation. + +For now, strategy-besu requires that solidity smart contracts in besu have a 'getAllAssetsIDs' function and that each function that changed an asset state, emits an event indexing the asset ID (we will introduce an interface soon). Lastly, strategy-fabric also requires that the fabric chaincode includes "GetAllAssetsKey" and "GetAllTxByKey" functions. + +Future versions of bungee may include smart contract interfaces for different ledgers. + + + +## Contributing +We welcome contributions to Hyperledger Cactus in many forms, and there’s always plenty to do! + +Please review [CONTIRBUTING.md](https://github.com/hyperledger/cactus/blob/main/CONTRIBUTING.md "CONTIRBUTING.md") to get started. + +## License +This distribution is published under the Apache License Version 2.0 found in the [LICENSE ](https://github.com/hyperledger/cactus/blob/main/LICENSE "LICENSE ")file. \ No newline at end of file diff --git a/packages/cactus-plugin-bungee/package.json b/packages/cactus-plugin-bungee/package.json index 6b00b03d90a..78478ba8b9c 100644 --- a/packages/cactus-plugin-bungee/package.json +++ b/packages/cactus-plugin-bungee/package.json @@ -64,8 +64,13 @@ "@hyperledger/cactus-plugin-object-store-ipfs": "2.0.0-alpha.2", "@hyperledger/cactus-test-tooling": "2.0.0-alpha.2", "axios": "1.6.0", + "body-parser": "1.20.2", + "fs-extra": "10.1.0", + "key-encoder": "2.0.3", "typescript-optional": "2.0.1", - "uuid": "9.0.1" + "uuid": "9.0.1", + "web3": "1.6.1", + "web3-core": "1.6.1" }, "devDependencies": { "@types/body-parser": "1.19.4", @@ -75,7 +80,8 @@ "@types/tape": "4.13.4", "@types/uuid": "9.0.6", "express": "4.18.2", - "fabric-network": "2.2.20" + "fabric-network": "2.2.20", + "socket.io": "4.5.4" }, "engines": { "node": ">=18", diff --git a/packages/cactus-plugin-bungee/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cactus-plugin-bungee/src/main/typescript/generated/openapi/typescript-axios/api.ts index 6042dbfc007..721d0192b90 100644 --- a/packages/cactus-plugin-bungee/src/main/typescript/generated/openapi/typescript-axios/api.ts +++ b/packages/cactus-plugin-bungee/src/main/typescript/generated/openapi/typescript-axios/api.ts @@ -22,6 +22,7 @@ import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObj import type { RequestArgs } from './base'; // @ts-ignore import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError } from './base'; +import { NetworkDetails } from '../../../strategy/obtain-ledger-strategy'; /** * @@ -34,7 +35,12 @@ export interface CreateViewRequest { * @type {string} * @memberof CreateViewRequest */ - 'x'?: string; + 'stateIds'?: string[]; + 'tI'?: string; + 'tF'?: string; + 'viewID'?: string; + 'strategyId': string; + 'networkDetails': NetworkDetails; } /** * @@ -47,7 +53,7 @@ export interface CreateViewResponse { * @type {string} * @memberof CreateViewResponse */ - 'y'?: string; + 'view'?: string; } /** diff --git a/packages/cactus-plugin-bungee/src/main/typescript/plugin-bungee-benchmark.ts b/packages/cactus-plugin-bungee/src/main/typescript/plugin-bungee-benchmark.ts deleted file mode 100644 index 87f504a77e7..00000000000 --- a/packages/cactus-plugin-bungee/src/main/typescript/plugin-bungee-benchmark.ts +++ /dev/null @@ -1,450 +0,0 @@ -import { Server } from "http"; - -import { Server as SecureServer } from "https"; - -import { v4 as uuidv4 } from "uuid"; - -import { PluginRegistry } from "@hyperledger/cactus-core"; - -import { - Configuration, - ICactusPluginOptions, -} from "@hyperledger/cactus-core-api"; - -import { - IJsObjectSignerOptions, - JsObjectSigner, - Logger, - LoggerProvider, - LogLevelDesc, -} from "@hyperledger/cactus-common"; - -import { ICactusApiServerOptions } from "@hyperledger/cactus-cmd-api-server"; - -import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; - -import { - DefaultApi as FabricApi, - RunTransactionRequest as FabricRunTransactionRequest, - FabricSigningCredential, - FabricContractInvocationType, -} from "@hyperledger/cactus-plugin-ledger-connector-fabric"; -import { Utils } from "./utils"; -import { Transaction } from "./view-creation/transaction"; -import { Proof } from "./view-creation/proof"; -import { State } from "./view-creation/state"; -import { View } from "./view-creation/view"; -import { Snapshot } from "./view-creation/snapshot"; -import path from "path"; - -export interface IPluginBUNGEEOptions extends ICactusPluginOptions { - instanceId: string; - participant: string; - - fabricPath?: string; - fabricSigningCredential?: FabricSigningCredential; - fabricChannelName?: string; - fabricContractName?: string; - fabricAssetID?: string; - fabricAssetSize?: string; - fabricConfig?: Configuration; - fabricApi?: FabricApi; - - logLevel?: LogLevelDesc; - keychainId?: string; - keychain?: PluginKeychainMemory; - apiServerOptions?: ICactusApiServerOptions; - httpApi?: Server | SecureServer; - disableSignalHandlers?: true; -} - -export class PluginBUNGEEBenchmark { - private bungeeSigner: JsObjectSigner; - private privKeyBungee: string; - private pubKeyBungee: string; - private tI: string; - private tF: string; - - private participant; - - private ledgerAssetsKey: string[]; - private ledgerStates: Map; //Key, state - private states: State[]; - public fabricApi?: FabricApi; - public fabricSigningCredential?: FabricSigningCredential; - public fabricChannelName?: string; - public fabricContractName?: string; - public fabricAssetID?: string; - public fabricAssetSize?: string; - private readonly instanceId: string; - private readonly className: string; - private level: LogLevelDesc; - private logger: Logger; - public pluginRegistry: PluginRegistry; - private tsStartGetAllAssetsKey: number; - private tsEndGetAllAssetsKey: number; - private tsStartGetAllTxByKey: number; - private tsEndGetAllTxByKey: number; - private tsStartfabricGetTxReceiptByTxIDV1: number; - private tsEndfabricGetTxReceiptByTxIDV1: number; - private tsStartgenerateLedgerStates: number; - private tsEndgenerateLedgerStates: number; - private tsStartgenerateSnapshot: number; - private tsEndgenerateSnapshot: number; - private tsStartGenerateView: number; - private tsEndGenerateView: number; - private fileNameDate = Date.now(); - - constructor(public readonly options: IPluginBUNGEEOptions) { - this.tsStartGetAllAssetsKey = 0; - this.tsEndGetAllAssetsKey = 0; - this.tsStartGetAllTxByKey = 0; - this.tsEndGetAllTxByKey = 0; - this.tsStartfabricGetTxReceiptByTxIDV1 = 0; - this.tsEndfabricGetTxReceiptByTxIDV1 = 0; - this.tsStartgenerateLedgerStates = 0; - this.tsEndgenerateLedgerStates = 0; - this.tsStartgenerateSnapshot = 0; - this.tsEndgenerateSnapshot = 0; - this.tsStartGenerateView = 0; - this.tsEndGenerateView = 0; - - this.className = "pluginBUNGEE"; - this.level = options.logLevel || "INFO"; - const label = this.getClassName(); - const level = this.level; - this.logger = LoggerProvider.getOrCreate({ label, level }); - - const keysRelPath = "../keys/"; - const pubKeyPath = path.join(__dirname, keysRelPath, "./bungee_pub.pem"); - const privKeyPath = path.join(__dirname, keysRelPath, "./bungee_priv.pem"); - this.pubKeyBungee = Utils.readKeyFromFile(pubKeyPath); - this.privKeyBungee = Utils.readKeyFromFile(privKeyPath); - const bungeeSignerOptions: IJsObjectSignerOptions = { - privateKey: this.privKeyBungee, - logLevel: "debug", - }; - this.bungeeSigner = new JsObjectSigner(bungeeSignerOptions); - - this.instanceId = uuidv4(); - this.participant = options.participant; - this.ledgerAssetsKey = []; - this.ledgerStates = new Map(); - this.states = []; - this.tI = ""; - this.tF = ""; - - this.pluginRegistry = new PluginRegistry(); - this.fabricApi = options.fabricApi; - - if (options.fabricPath != undefined) this.defineFabricConnection(options); - } - - public getInstanceId(): string { - return this.instanceId; - } - - public getPackageName(): string { - return `@hyperledger/cactus-plugin-bungee`; - } - - public getClassName(): string { - return this.className; - } - - public async onPluginInit(): Promise { - return; - } - - private defineFabricConnection(options: IPluginBUNGEEOptions): void { - this.logger.info(`OPTIONS:: ${options}`); - const fnTag = `${this.className}#defineFabricConnection()`; - - const config = new Configuration({ basePath: options.fabricPath }); - const apiClient = new FabricApi(config); - this.fabricApi = apiClient; - const notEnoughFabricParams: boolean = - options.fabricSigningCredential == undefined || - options.fabricChannelName == undefined || - options.fabricContractName == undefined || - options.fabricAssetID == undefined; - if (notEnoughFabricParams) { - throw new Error( - `${fnTag}, fabric params missing should have: signing credentials, contract name, channel name, asset ID`, - ); - } - this.fabricSigningCredential = options.fabricSigningCredential; - this.fabricChannelName = options.fabricChannelName; - this.fabricContractName = options.fabricContractName; - this.fabricAssetID = options.fabricAssetID; - this.fabricAssetSize = options.fabricAssetSize - ? options.fabricAssetSize - : "1"; - } - - /** - * - * @abstract Create ledger state. Get all keys, iterate every key and get the respective transactions. For each transaction get the receipt - * */ - public async generateLedgerStates(): Promise { - this.tsStartgenerateLedgerStates = performance.now(); - this.logger.info(`Generating ledger snapshot`); - - const assetsKey = await this.getAllAssetsKey(); - this.ledgerAssetsKey = assetsKey.split(","); - - //For each key in ledgerAssetsKey - for (const assetKey of this.ledgerAssetsKey) { - const assetValues: string[] = []; - const txWithTimeS: Transaction[] = []; - - this.logger.info(assetKey); - const txs = await this.getAllTxByKey(assetKey); - - //For each tx get receipt - for (const tx of txs) { - const endorsements: Proof[] = []; - const receipt = JSON.parse( - await this.fabricGetTxReceiptByTxIDV1(tx.getId()), - ); - - // Checks if tx was made by participant - if (receipt.transactionCreator.mspid != this.participant) { - continue; - } - - assetValues.push(JSON.parse(receipt.rwsetWriteData).Value.toString()); - - //Save endorsements of tx - for (const endorsement of receipt.transactionEndorsement) { - const signature64 = Buffer.from(endorsement.signature).toString( - "base64", - ); - endorsements.push( - new Proof(endorsement.mspid, endorsement.endorserID, signature64), - ); - } - tx.defineTxProofs(endorsements); - txWithTimeS.push(tx); - } - const state = new State(assetKey, assetValues, txWithTimeS); - this.ledgerStates.set(assetKey, state); - this.states.push(state); - } - - this.ledgerStates.forEach((state: State, keyId: string) => { - console.log(keyId, state); - const assetState = this.ledgerStates.get(keyId); - if (assetState != undefined) { - this.logger.info(assetState); - this.logger.info(JSON.parse(assetState.getStateJson())); - } - }); - - // TESTS ONLY -> next receive ti tf - const asset2 = this.ledgerStates.get("ASSET2"); - - if (asset2 != undefined) { - this.tI = asset2.getInitialTime(); - } - - const asset9 = this.ledgerStates.get("ASSET9"); - if (asset9 != undefined) { - // this.tF = asset9.getTimeForTxN(5); - this.tF = asset9.getFinalTime(); - } - - this.tsEndgenerateLedgerStates = performance.now(); - - return ""; - } - - /** - * - * @abstract Returns Snapshot - * */ - public generateSnapshot(): Snapshot { - this.tsStartgenerateSnapshot = performance.now(); - const snapShotId = uuidv4(); - const snapshot = new Snapshot(snapShotId, this.participant, this.states); - this.tsEndgenerateSnapshot = performance.now(); - return snapshot; - } - - /** - * - * @abstract Returns view. Generate final view with signature - * - * @param snapshot - Ledger Snapshot - * */ - public generateView(snapshot: Snapshot): string { - this.tsStartGenerateView = performance.now(); - const crypto = require("crypto"); - - this.logger.warn(this.pubKeyBungee); - this.logger.warn(this.privKeyBungee); - const view = new View(this.tI, this.tF, snapshot); - - const signer = crypto.createSign("SHA256"); - signer.write(JSON.stringify(view)); - signer.end(); - - this.logger.warn(view.getViewStr()); - - const signature = signer.sign(this.privKeyBungee, "base64"); - - // this.saveToFile(__dirname + "/../../view/signed.json", JSON.stringify(view)); - - const signedView = { View: view, Signature: signature }; - - this.saveToFile( - __dirname + "/../../view/viewFile_" + this.fileNameDate + ".json", - JSON.stringify(signedView, null, 2), - ); - - this.tsEndGenerateView = performance.now(); - return JSON.stringify(signedView); - } - - /** - * - * @abstract Returns transaction receipt. - * - * @param transactionId - Transaction id to return the receipt - * */ - async fabricGetTxReceiptByTxIDV1(transactionId: string): Promise { - this.tsStartfabricGetTxReceiptByTxIDV1 = performance.now(); - - const receiptLockRes = await this.fabricApi?.getTransactionReceiptByTxIDV1({ - signingCredential: this.fabricSigningCredential, - channelName: this.fabricChannelName, - contractName: "qscc", - invocationType: FabricContractInvocationType.Call, - methodName: "GetBlockByTxID", - params: [this.fabricChannelName, transactionId], - } as FabricRunTransactionRequest); - - this.tsEndfabricGetTxReceiptByTxIDV1 = performance.now(); - return JSON.stringify(receiptLockRes?.data); - } - - /** - * - * @abstract Returns all assets key found in the world state. - * */ - async getAllAssetsKey(): Promise { - this.tsStartGetAllAssetsKey = performance.now(); - const response = await this.fabricApi?.runTransactionV1({ - signingCredential: this.fabricSigningCredential, - channelName: this.fabricChannelName, - contractName: this.fabricContractName, - methodName: "GetAllAssetsKey", - invocationType: FabricContractInvocationType.Call, - params: [], - } as FabricRunTransactionRequest); - - if (response != undefined) { - this.tsEndGetAllAssetsKey = performance.now(); - return response.data.functionOutput; - } - - return "response undefined"; - } - - /** - * - * @abstract Returns an array of all transactions for a specific key. - * - * @param key - Key used to get correspondent transactions - * */ - async getAllTxByKey(key: string): Promise { - this.tsStartGetAllTxByKey = performance.now(); - const response = await this.fabricApi?.runTransactionV1({ - signingCredential: this.fabricSigningCredential, - channelName: this.fabricChannelName, - contractName: this.fabricContractName, - methodName: "GetAllTxByKey", - invocationType: FabricContractInvocationType.Call, - params: [key], - } as FabricRunTransactionRequest); - - if (response != undefined) { - this.tsEndGetAllTxByKey = performance.now(); - return Utils.txsStringToTxs(response.data.functionOutput); - } - - return []; - } - - /** - * - * @abstract Returns all the transactions for a specific key in string format. - * - * @param key - Key (id) used to get correspondent transactions - * */ - async getAllTxByKeyString(key: string): Promise { - const response = await this.fabricApi?.runTransactionV1({ - signingCredential: this.fabricSigningCredential, - channelName: this.fabricChannelName, - contractName: this.fabricContractName, - methodName: "GetAllTxByKey", - invocationType: FabricContractInvocationType.Call, - params: [key], - } as FabricRunTransactionRequest); - - if (response != undefined) { - return response.data.functionOutput; - } - - return ""; - } - - public generateBenchmarkReport( - numberOfTransactions: number, - tsStartTotalTime: number, - tsEndTotalTime: number, - tsStartTransactionsTime: number, - tsEndTransactionsTime: number, - ): void { - const report = { - tsStartGetAllAssetsKey: this.tsStartGetAllAssetsKey, - tsEndGetAllAssetsKey: this.tsEndGetAllAssetsKey, - tsStartGetAllTxByKey: this.tsStartGetAllTxByKey, - tsEndGetAllTxByKey: this.tsEndGetAllTxByKey, - tsStartfabricGetTxReceiptByTxIDV1: this.tsStartfabricGetTxReceiptByTxIDV1, - numberOfTransactions: numberOfTransactions, - tsEndfabricGetTxReceiptByTxIDV1: this.tsEndfabricGetTxReceiptByTxIDV1, - tsStartgenerateLedgerStates: this.tsStartgenerateLedgerStates, - tsEndgenerateLedgerStates: this.tsEndgenerateLedgerStates, - tsStartgenerateSnapshot: this.tsStartgenerateSnapshot, - tsEndgenerateSnapshot: this.tsEndgenerateSnapshot, - tsStartGenerateView: this.tsStartGenerateView, - tsEndGenerateView: this.tsEndGenerateView, - tsStartTotalTime: tsStartTotalTime, - tsEndTotalTime: tsEndTotalTime, - tsStartTransactionsTime: tsStartTransactionsTime, - tsEndTransactionsTime: tsEndTransactionsTime, - }; - const reportString = JSON.stringify(report, null, 2); - this.saveToFile( - __dirname + "/../../report/report_" + this.fileNameDate + ".json", - reportString, - ); - } - - /** - * - * @abstract Save view in json file. - * - * @param fileName - File name or path + file name - * @param data - View in a string format to write inside the json file - * */ - public saveToFile(fileName: string, data: string): void { - const fs = require("fs"); - fs.writeFileSync(fileName, data, function (err: boolean) { - if (err) { - return console.log("error"); - } - }); - } -} diff --git a/packages/cactus-plugin-bungee/src/main/typescript/plugin-bungee.ts b/packages/cactus-plugin-bungee/src/main/typescript/plugin-bungee.ts index a55fff8aa85..4d66b3dbe51 100644 --- a/packages/cactus-plugin-bungee/src/main/typescript/plugin-bungee.ts +++ b/packages/cactus-plugin-bungee/src/main/typescript/plugin-bungee.ts @@ -1,85 +1,68 @@ -import { Server } from "http"; -import { Optional } from "typescript-optional"; -import { v4 as uuidV4 } from "uuid"; -import { Server as SecureServer } from "https"; -import OAS from "../json/openapi.json"; -import type { Express } from "express"; - -import { - Configuration, - ICactusPlugin, - ICactusPluginOptions, - IPluginWebService, - IWebServiceEndpoint, -} from "@hyperledger/cactus-core-api"; - import { Checks, IJsObjectSignerOptions, JsObjectSigner, + LogLevelDesc, Logger, LoggerProvider, - LogLevelDesc, + Secp256k1Keys, } from "@hyperledger/cactus-common"; +import { v4 as uuidV4 } from "uuid"; +import { + ICactusPlugin, + ICactusPluginOptions, + IPluginWebService, + IWebServiceEndpoint, +} from "@hyperledger/cactus-core-api"; +import { State } from "./view-creation/state"; +import { ClientEndpointV1 } from "./web-services/client-endpoint"; +import OAS from "../json/openapi.json"; +import type { Express } from "express"; +import { Optional } from "typescript-optional"; +import { Server } from "http"; +import { Server as SecureServer } from "https"; import { CreateViewRequest, CreateViewResponse, } from "./generated/openapi/typescript-axios"; - -import { - DefaultApi as FabricApi, - RunTransactionRequest as FabricRunTransactionRequest, - FabricSigningCredential, - FabricContractInvocationType, -} from "@hyperledger/cactus-plugin-ledger-connector-fabric"; - -import { Utils } from "./utils"; -import { Transaction } from "./view-creation/transaction"; -import { Proof } from "./view-creation/proof"; -import { State } from "./view-creation/state"; -import { View } from "./view-creation/view"; import { Snapshot } from "./view-creation/snapshot"; -import path from "path"; -import { ClientEndpointV1 } from "./web-services/client-endpoint"; +import { View } from "./view-creation/view"; +import { + NetworkDetails, + ObtainLedgerStrategy, +} from "./strategy/obtain-ledger-strategy"; + +export interface IKeyPair { + publicKey: Uint8Array; + privateKey: Uint8Array; +} export interface IPluginBUNGEEOptions extends ICactusPluginOptions { - participant: string; - fabricPath?: string; - fabricSigningCredential?: FabricSigningCredential; - fabricChannelName?: string; - fabricContractName?: string; - fabricAssetID?: string; - fabricAssetSize?: string; - fabricConfig?: Configuration; - fabricApi?: FabricApi; + instanceId: string; + keyPair?: IKeyPair; logLevel?: LogLevelDesc; + disableSignalHandlers?: true; } export class PluginBUNGEE implements ICactusPlugin, IPluginWebService { public static readonly CLASS_NAME = "PluginBUNGEE"; + private readonly instanceId: string; + private log: Logger; + private keyPair: IKeyPair; private bungeeSigner: JsObjectSigner; private privKeyBungee: string; private pubKeyBungee: string; - private tI: string; - private tF: string; - - private participant; - - private ledgerAssetsKey: string[]; - private ledgerStates: Map; //Key, state - private states: State[]; - public fabricApi?: FabricApi; - public fabricSigningCredential?: FabricSigningCredential; - public fabricChannelName?: string; - public fabricContractName?: string; - public fabricAssetID?: string; - public fabricAssetSize?: string; - private readonly instanceId: string; + + private strategies: Map; + + //protected ledgerStates: Map; //Key, state + //protected states: State[]; + private level: LogLevelDesc; private endpoints: IWebServiceEndpoint[] | undefined; @@ -87,39 +70,48 @@ export class PluginBUNGEE implements ICactusPlugin, IPluginWebService { const fnTag = `${this.className}#constructor()`; Checks.truthy(options, `${fnTag} arg options`); Checks.truthy(options.instanceId, `${fnTag} options.instanceId`); + this.level = options.logLevel || "INFO"; + this.strategies = new Map(); const label = this.className; const level = this.level; + this.log = LoggerProvider.getOrCreate({ label, level }); this.instanceId = options.instanceId; - const keysRelPath = "../keys/"; - const pubKeyPath = path.join(__dirname, keysRelPath, "./bungee_pub.pem"); - const privKeyPath = path.join(__dirname, keysRelPath, "./bungee_priv.pem"); - this.pubKeyBungee = Utils.readKeyFromFile(pubKeyPath); - this.privKeyBungee = Utils.readKeyFromFile(privKeyPath); + this.keyPair = options.keyPair + ? options.keyPair + : Secp256k1Keys.generateKeyPairsBuffer(); + this.privKeyBungee = Buffer.from(this.keyPair.privateKey).toString("hex"); + this.pubKeyBungee = Buffer.from(this.keyPair.publicKey).toString("hex"); const bungeeSignerOptions: IJsObjectSignerOptions = { privateKey: this.privKeyBungee, logLevel: "debug", }; this.bungeeSigner = new JsObjectSigner(bungeeSignerOptions); - - this.participant = options.participant; - this.ledgerAssetsKey = []; - this.ledgerStates = new Map(); - this.states = []; - this.tI = ""; - this.tF = ""; - - this.fabricApi = options.fabricApi; - - if (options.fabricPath != undefined) this.defineFabricConnection(options); } public get className(): string { return PluginBUNGEE.CLASS_NAME; } + public get logger(): Logger { + return this.log; + } + + public addStrategy(strategyId: string, strategy: ObtainLedgerStrategy) { + if (this.strategies.get(strategyId) == undefined) { + this.strategies.set(strategyId, strategy); + } else { + throw Error("Strategy " + strategyId + " already exists."); + } + } + public getStrategy(strategyId: string): ObtainLedgerStrategy | undefined { + return this.strategies.get(strategyId); + } + public getSupportedStrategies(): string[] { + return Array.from(this.strategies.keys()); + } public getOpenApiSpec(): unknown { return OAS; @@ -128,7 +120,6 @@ export class PluginBUNGEE implements ICactusPlugin, IPluginWebService { public async shutdown(): Promise { this.log.info(`Shutting down ${this.className}...`); } - public getPackageName(): string { return `@hyperledger/cactus-plugin-bungee`; } @@ -164,255 +155,81 @@ export class PluginBUNGEE implements ICactusPlugin, IPluginWebService { return this.instanceId; } - private defineFabricConnection(options: IPluginBUNGEEOptions): void { - this.log.info(`OPTIONS:: ${options}`); - const fnTag = `${this.className}#defineFabricConnection()`; - - const config = new Configuration({ basePath: options.fabricPath }); - const apiClient = new FabricApi(config); - this.fabricApi = apiClient; - const notEnoughFabricParams: boolean = - options.fabricSigningCredential == undefined || - options.fabricChannelName == undefined || - options.fabricContractName == undefined || - options.fabricAssetID == undefined; - if (notEnoughFabricParams) { - throw new Error( - `${fnTag}, fabric params missing should have: signing credentials, contract name, channel name, asset ID`, - ); - } - this.fabricSigningCredential = options.fabricSigningCredential; - this.fabricChannelName = options.fabricChannelName; - this.fabricContractName = options.fabricContractName; - this.fabricAssetID = options.fabricAssetID; - this.fabricAssetSize = options.fabricAssetSize - ? options.fabricAssetSize - : "1"; - } - async onCreateView(request: CreateViewRequest): Promise { - const fnTag = `${this.className}#onCreateView()`; - this.log.info(`${fnTag}, request received, ${request}`); - const response = this.generateView(this.generateSnapshot()); + //const fnTag = `${this.className}#onCreateView()`; + const ti: string = request.tI ? request.tI : "0"; + const tf: string = request.tF ? request.tF : "9999999999999"; + const stateIds: string[] = request.stateIds ? request.stateIds : []; + + const snapshot = await this.generateSnapshot( + stateIds, + request.strategyId, + request.networkDetails, + ); + this.logger.info("Generating view for request: ", request); + const response = JSON.stringify( + this.generateView(snapshot, ti, tf, request.viewID), + ); return { - y: response, + view: response, }; } - /** - * - * @abstract Create ledger state. Get all keys, iterate every key and get the respective transactions. For each transaction get the receipt - * */ - public async generateLedgerStates(): Promise { - this.log.info(`Generating ledger snapshot`); - - const assetsKey = await this.getAllAssetsKey(); - this.ledgerAssetsKey = assetsKey.split(","); - - //For each key in ledgerAssetsKey - for (const assetKey of this.ledgerAssetsKey) { - const assetValues: string[] = []; - const txWithTimeS: Transaction[] = []; - - this.log.info(assetKey); - const txs = await this.getAllTxByKey(assetKey); - - //For each tx get receipt - for (const tx of txs) { - const endorsements: Proof[] = []; - const receipt = JSON.parse( - await this.fabricGetTxReceiptByTxIDV1(tx.getId()), - ); - - // Checks if tx was made by participant - if (receipt.transactionCreator.mspid != this.participant) { - continue; - } - - assetValues.push(JSON.parse(receipt.rwsetWriteData).Value.toString()); - - //Save endorsements of tx - for (const endorsement of receipt.transactionEndorsement) { - const signature64 = Buffer.from(endorsement.signature).toString( - "base64", - ); - endorsements.push( - new Proof(endorsement.mspid, endorsement.endorserID, signature64), - ); - } - tx.defineTxProofs(endorsements); - txWithTimeS.push(tx); - } - const state = new State(assetKey, assetValues, txWithTimeS); - this.ledgerStates.set(assetKey, state); - this.states.push(state); + public generateView( + snapshot: Snapshot, + tI: string, + tF: string, + id: string | undefined, + ): { view?: View; signature?: string } { + if ( + parseInt(tI) > parseInt(snapshot.getTF()) || + parseInt(tF) < parseInt(snapshot.getTI()) || + parseInt(tI) > parseInt(tF) + ) { + return {}; } + const view = new View(tI, tF, snapshot, id); + snapshot.pruneStates(tI, tF); - this.ledgerStates.forEach((state: State, keyId: string) => { - console.log(keyId, state); - const assetState = this.ledgerStates.get(keyId); - if (assetState != undefined) { - this.log.info(assetState); - this.log.info(JSON.parse(assetState.getStateJson())); - } - }); - - // TESTS ONLY -> next receive ti tf - const car2 = this.ledgerStates.get("CAR2"); - - if (car2 != undefined) { - this.tI = car2.getTimeForTxN(2); - this.tF = car2.getTimeForTxN(1); - } + const signature = this.sign(JSON.stringify(view)); - return ""; + return { view: view, signature: signature }; } - /** - * - * @abstract Returns Snapshot - * */ - public generateSnapshot(): Snapshot { - const snapShotId = uuidV4(); - const snapshot = new Snapshot(snapShotId, this.participant, this.states); - return snapshot; + sign(msg: string): string { + return Buffer.from(this.bungeeSigner.sign(msg)).toString("hex"); } - /** - * - * @abstract Returns view. Generate final view with signature - * - * @param snapshot - Ledger Snapshot - * */ - public generateView(snapshot: Snapshot): string { - const crypto = require("crypto"); - - this.log.warn(this.pubKeyBungee); - this.log.warn(this.privKeyBungee); - const view = new View(this.tI, this.tF, snapshot); - - const signer = crypto.createSign("SHA256"); - signer.write(JSON.stringify(view)); - signer.end(); - - this.log.warn(view.getViewStr()); - - const signature = signer.sign(this.privKeyBungee, "base64"); - - this.saveToFile( - __dirname + "/../../view/signed.json", - JSON.stringify(view), - ); - - const signedView = { View: view, Signature: signature }; - - this.saveToFile( - __dirname + "/../../view/viewFile.json", - JSON.stringify(signedView, null, 2), - ); - - return JSON.stringify(signedView); - } - - /** - * - * @abstract Returns transaction receipt. - * - * @param transactionId - Transaction id to return the receipt - * */ - async fabricGetTxReceiptByTxIDV1(transactionId: string): Promise { - const receiptLockRes = await this.fabricApi?.getTransactionReceiptByTxIDV1({ - signingCredential: this.fabricSigningCredential, - channelName: this.fabricChannelName, - contractName: "qscc", - invocationType: FabricContractInvocationType.Call, - methodName: "GetBlockByTxID", - params: [this.fabricChannelName, transactionId], - } as FabricRunTransactionRequest); - - return JSON.stringify(receiptLockRes?.data); - } - - /** - * - * @abstract Returns all assets key found in the world state. - * */ - async getAllAssetsKey(): Promise { - const response = await this.fabricApi?.runTransactionV1({ - signingCredential: this.fabricSigningCredential, - channelName: this.fabricChannelName, - contractName: this.fabricContractName, - methodName: "GetAllAssetsKey", - invocationType: FabricContractInvocationType.Call, - params: [], - } as FabricRunTransactionRequest); - - if (response != undefined) { - return response.data.functionOutput; - } - - return "response undefined"; - } - - /** - * - * @abstract Returns an array of all transactions for a specific key. - * - * @param key - Key used to get correspondent transactions - * */ - async getAllTxByKey(key: string): Promise { - const response = await this.fabricApi?.runTransactionV1({ - signingCredential: this.fabricSigningCredential, - channelName: this.fabricChannelName, - contractName: this.fabricContractName, - methodName: "GetAllTxByKey", - invocationType: FabricContractInvocationType.Call, - params: [key], - } as FabricRunTransactionRequest); - - if (response != undefined) { - return Utils.txsStringToTxs(response.data.functionOutput); + public async generateSnapshot( + stateIds: string[], + strategyId: string, + networkDetails: NetworkDetails, + ): Promise { + const strategy = this.getStrategy(strategyId); + if (strategy == undefined) { + throw Error("Strategy " + strategyId + " is undefined/unsupported"); } - return []; - } + const ledgerStates = await strategy.generateLedgerStates( + stateIds, + networkDetails, + ); - /** - * - * @abstract Returns all the transactions for a specific key in string format. - * - * @param key - Key (id) used to get correspondent transactions - * */ - async getAllTxByKeyString(key: string): Promise { - const response = await this.fabricApi?.runTransactionV1({ - signingCredential: this.fabricSigningCredential, - channelName: this.fabricChannelName, - contractName: this.fabricContractName, - methodName: "GetAllTxByKey", - invocationType: FabricContractInvocationType.Call, - params: [key], - } as FabricRunTransactionRequest); - - if (response != undefined) { - return response.data.functionOutput; + const states: State[] = []; + for (const key of ledgerStates.keys()) { + if (stateIds.includes(key) || stateIds.length == 0) { + states.push(ledgerStates.get(key) as State); + } } - return ""; - } + const snapShotId = uuidV4(); + const snapshot = new Snapshot( + snapShotId, + networkDetails.participant, + states, + ); + snapshot.update_TI_TF(); - /** - * - * @abstract Save view in json file. - * - * @param fileName - File name or path + file name - * @param data - View in a string format to write inside the json file - * */ - public saveToFile(fileName: string, data: string): void { - const fs = require("fs"); - fs.writeFileSync(fileName, data, function (err: boolean) { - if (err) { - return console.log("error"); - } - }); + return snapshot; } } diff --git a/packages/cactus-plugin-bungee/src/main/typescript/public-api.ts b/packages/cactus-plugin-bungee/src/main/typescript/public-api.ts index db2130329d8..4beb7f798be 100644 --- a/packages/cactus-plugin-bungee/src/main/typescript/public-api.ts +++ b/packages/cactus-plugin-bungee/src/main/typescript/public-api.ts @@ -3,7 +3,7 @@ import { PluginFactoryBUNGEE } from "./plugin-factory-bungee"; export { PluginBUNGEE, IPluginBUNGEEOptions } from "./plugin-bungee"; -export async function createPluginFactory( +export async function createBesuPluginFactory( pluginFactoryOptions: IPluginFactoryOptions, ): Promise { return new PluginFactoryBUNGEE(pluginFactoryOptions); diff --git a/packages/cactus-plugin-bungee/src/main/typescript/strategy/obtain-ledger-strategy.ts b/packages/cactus-plugin-bungee/src/main/typescript/strategy/obtain-ledger-strategy.ts new file mode 100644 index 00000000000..eeb1b68aa12 --- /dev/null +++ b/packages/cactus-plugin-bungee/src/main/typescript/strategy/obtain-ledger-strategy.ts @@ -0,0 +1,15 @@ +import { Logger } from "@hyperledger/cactus-common"; +import { State } from "../view-creation/state"; + +export interface NetworkDetails { + connectorApiPath: string; + participant: string; +} +export interface ObtainLedgerStrategy { + log: Logger; + + generateLedgerStates( + stateIds: string[], + networkDetails: NetworkDetails, + ): Promise>; +} diff --git a/packages/cactus-plugin-bungee/src/main/typescript/strategy/strategy-besu.ts b/packages/cactus-plugin-bungee/src/main/typescript/strategy/strategy-besu.ts new file mode 100644 index 00000000000..42d45707be9 --- /dev/null +++ b/packages/cactus-plugin-bungee/src/main/typescript/strategy/strategy-besu.ts @@ -0,0 +1,188 @@ +import { NetworkDetails, ObtainLedgerStrategy } from "./obtain-ledger-strategy"; +import { + LogLevelDesc, + Logger, + LoggerProvider, +} from "@hyperledger/cactus-common"; +import { + DefaultApi as BesuApi, + EthContractInvocationType, + EvmBlock, + EvmLog, + GetBlockV1Request, + GetPastLogsV1Request, + GetTransactionV1Request, + InvokeContractV1Request, + Web3SigningCredential, +} from "@hyperledger/cactus-plugin-ledger-connector-besu"; +import { State } from "../view-creation/state"; +import { StateProof } from "../view-creation/state-proof"; +import { Configuration } from "@hyperledger/cactus-core-api"; +import { Transaction } from "../view-creation/transaction"; +import Web3 from "web3"; +import { Proof } from "../view-creation/proof"; +import { TransactionProof } from "../view-creation/transaction-proof"; + +export interface BesuNetworkDetails extends NetworkDetails { + signingCredential: Web3SigningCredential; + keychainId: string; + contractName: string; + contractAddress: string; +} +export class StrategyBesu implements ObtainLedgerStrategy { + public static readonly CLASS_NAME = "StrategyBesu"; + + public log: Logger; + + constructor(level: LogLevelDesc) { + this.log = LoggerProvider.getOrCreate({ + label: StrategyBesu.CLASS_NAME, + level, + }); + } + + public async generateLedgerStates( + stateIds: string[], + networkDetails: BesuNetworkDetails, + ): Promise> { + this.log.debug(`Generating ledger snapshot`); + const config = new Configuration({ + basePath: networkDetails.connectorApiPath, + }); + const besuApi = new BesuApi(config); + + const ledgerStates = new Map(); + const assetsKey = + stateIds.length == 0 + ? ((await this.getAllAssetsKey(networkDetails, besuApi)) as string[]) + : stateIds; + this.log.debug("Current assets detected to capture: " + assetsKey); + for (const assetKey of assetsKey) { + const { transactions, values, blocks } = await this.getAllInfoByKey( + assetKey, + networkDetails, + besuApi, + ); + + const state = new State(assetKey, values, transactions); + + const stateProof = new StateProof( + state.getValue(), + parseInt(state.getVersion()), + state.getId(), + ); + const blocksHash: string[] = []; + for (const block of blocks.values()) { + if (blocksHash.indexOf(block.hash as string) !== -1) { + continue; + } + blocksHash.push(block.hash as string); + stateProof.addBlock({ + blockHash: block.hash as string, + blockCreator: block.miner as string, + blockSigners: [], // FIXME: query blocksigners (blockchain specific) + }); + } + state.setStateProof([]); + ledgerStates.set(assetKey, state); + } + return ledgerStates; + } + + async getAllAssetsKey( + networkDetails: BesuNetworkDetails, + api: BesuApi, + ): Promise { + const parameters = { + contractName: networkDetails.contractName, + keychainId: networkDetails.keychainId, + invocationType: EthContractInvocationType.Call, + methodName: "getAllAssetsIDs", + params: [], + signingCredential: networkDetails.signingCredential, + gas: 1000000, + }; + const response = await api.invokeContractV1( + parameters as InvokeContractV1Request, + ); + if (response != undefined) { + return response.data.callOutput; + } + + return "response undefined"; + } + + async getAllInfoByKey( + key: string, + networkDetails: BesuNetworkDetails, + api: BesuApi, + ): Promise<{ + transactions: Transaction[]; + values: string[]; + blocks: Map; + }> { + const req = { + address: networkDetails.contractAddress, + topics: [[null], [Web3.utils.keccak256(key)]], //filter logs by asset key + }; + const response = await api.getPastLogsV1(req as GetPastLogsV1Request); + if (response == undefined) { + return { + transactions: [], + values: [], + blocks: new Map(), + }; + } + const decoded = response.data.logs as EvmLog[]; + const transactions: Transaction[] = []; + const blocks: Map = new Map(); + const values: string[] = []; + this.log.debug("Getting transaction logs for asset: " + key); + + for (const log of decoded) { + const txTx = await api.getTransactionV1({ + transactionHash: log.transactionHash, + } as GetTransactionV1Request); + + const txBlock = await api.getBlockV1({ + blockHashOrBlockNumber: log.blockHash, + } as GetBlockV1Request); + if (txTx == undefined || txBlock == undefined) { + this.log.debug( + "some error occurred fetching transaction or block info in ", + ); + return { + transactions: [], + values: [], + blocks: new Map(), + }; + } + this.log.debug( + "Transaction: " + + log.transactionHash + + "\nData: " + + JSON.stringify(log.data) + + "\n =========== \n", + ); + const proof = new Proof({ + creator: txTx.data.transaction.from as string, //no sig for besu + }); + const transaction: Transaction = new Transaction( + log.transactionHash, + txBlock.data.block.timestamp, + new TransactionProof(proof), + ); + transaction.setStateId(key); + transaction.setTarget(networkDetails.contractAddress as string); + transaction.setPayload( + txTx.data.transaction.input ? txTx.data.transaction.input : "", + ); //FIXME: payload = transaction input ? + transactions.push(transaction); + values.push(JSON.stringify(log.data)); + + blocks.set(transaction.getId(), txBlock.data.block); + } + + return { transactions: transactions, values: values, blocks: blocks }; + } +} diff --git a/packages/cactus-plugin-bungee/src/main/typescript/strategy/strategy-fabric.ts b/packages/cactus-plugin-bungee/src/main/typescript/strategy/strategy-fabric.ts new file mode 100644 index 00000000000..5872025fc20 --- /dev/null +++ b/packages/cactus-plugin-bungee/src/main/typescript/strategy/strategy-fabric.ts @@ -0,0 +1,227 @@ +import { + FabricSigningCredential, + DefaultApi as FabricApi, + Configuration, + FabricContractInvocationType, + RunTransactionRequest, +} from "@hyperledger/cactus-plugin-ledger-connector-fabric"; +import { NetworkDetails, ObtainLedgerStrategy } from "./obtain-ledger-strategy"; +import { + LogLevelDesc, + Logger, + LoggerProvider, +} from "@hyperledger/cactus-common"; +import { Transaction } from "../view-creation/transaction"; +import { Utils } from "../utils"; +import { State } from "../view-creation/state"; +import { StateProof } from "../view-creation/state-proof"; +import { Proof } from "../view-creation/proof"; +import { TransactionProof } from "../view-creation/transaction-proof"; + +export interface FabricNetworkDetails extends NetworkDetails { + signingCredential: FabricSigningCredential; + contractName: string; + channelName: string; +} +export class StrategyFabric implements ObtainLedgerStrategy { + public static readonly CLASS_NAME = "StrategyFabric"; + + public log: Logger; + + constructor(level: LogLevelDesc) { + this.log = LoggerProvider.getOrCreate({ + label: StrategyFabric.CLASS_NAME, + level, + }); + } + + public async generateLedgerStates( + stateIds: string[], + networkDetails: FabricNetworkDetails, + ): Promise> { + this.log.info(`Generating ledger snapshot`); + + const config = new Configuration({ + basePath: networkDetails.connectorApiPath, + }); + const fabricApi = new FabricApi(config); + + const assetsKey = + stateIds.length == 0 + ? (await this.getAllAssetsKey(fabricApi, networkDetails)).split(",") + : stateIds; + const ledgerStates = new Map(); + //For each key in ledgerAssetsKey + for (const assetKey of assetsKey) { + const assetValues: string[] = []; + const txWithTimeS: Transaction[] = []; + + const txs = await this.getAllTxByKey(assetKey, fabricApi, networkDetails); + //For each tx get receipt + for (const tx of txs) { + const receipt = JSON.parse( + await this.fabricGetTxReceiptByTxIDV1( + tx.getId(), + fabricApi, + networkDetails, + ), + ); + + assetValues.push(JSON.parse(receipt.rwsetWriteData).Value.toString()); + tx.setStateId(assetKey); + //tx.setPayload(); //FIXME check what to assign here + //tx.setTarget(); + + for (const endorsement of receipt.transactionEndorsement) { + const signature64 = Buffer.from(endorsement.signature).toString( + "base64", + ); + tx.addEndorser( + new Proof({ + mspid: endorsement.mspid, + creator: endorsement.endorserID, + signature: signature64, + }), + ); + } + txWithTimeS.push(tx); + } + const block = await this.fabricGetBlockByTxID( + txs[txs.length - 1].getId(), + fabricApi, + networkDetails, + ); + + const state = new State(assetKey, assetValues, txWithTimeS); + ledgerStates.set(assetKey, state); + const stateProof = new StateProof( + state.getValue(), + parseInt(state.getVersion()), + state.getId(), + ); + //only adding last block for each state, in the state proof + stateProof.addBlock({ + blockHash: block.hash, + blockCreator: "", + blockSigners: block.signers, + }); + } + return ledgerStates; + } + + async fabricGetTxReceiptByTxIDV1( + transactionId: string, + api: FabricApi, + networkDetails: FabricNetworkDetails, + ): Promise { + const receiptLockRes = await api.getTransactionReceiptByTxIDV1({ + signingCredential: networkDetails.signingCredential, + channelName: networkDetails.channelName, + contractName: "qscc", + invocationType: FabricContractInvocationType.Call, + methodName: "GetBlockByTxID", + params: [networkDetails.channelName, transactionId], + } as RunTransactionRequest); + return JSON.stringify(receiptLockRes?.data); + } + + async fabricGetBlockByTxID( + txId: string, + api: FabricApi, + netwokDetails: FabricNetworkDetails, + ): Promise<{ hash: string; signers: string[] }> { + const gatewayOptions = { + identity: netwokDetails.signingCredential.keychainRef, + wallet: { + keychain: { + keychainId: netwokDetails.signingCredential.keychainId, + keychainRef: netwokDetails.signingCredential.keychainRef, + }, + }, + }; + const getBlockReq = { + channelName: netwokDetails.channelName as string, + gatewayOptions, + query: { + transactionId: txId, + }, + skipDecode: false, + }; + + const getBlockResponse = await api.getBlockV1(getBlockReq); + + const block = JSON.parse( + JSON.stringify(getBlockResponse?.data), + ).decodedBlock; + + const blockSig = block.metadata.metadata[0].signatures; + const sigs = []; + for (const sig of blockSig) { + sigs.push(JSON.stringify(sig)); + } + + return { + hash: Utils.bufArray2HexStr(block.header.data_hash.data), + signers: sigs, + }; + } + + async getAllAssetsKey( + api: FabricApi, + netwokDetails: FabricNetworkDetails, + ): Promise { + const response = await api.runTransactionV1({ + signingCredential: netwokDetails.signingCredential, + channelName: netwokDetails.channelName, + contractName: netwokDetails.contractName, + methodName: "GetAllAssetsKey", + invocationType: FabricContractInvocationType.Call, + params: [], + } as RunTransactionRequest); + + if (response != undefined) { + return response.data.functionOutput; + } + + return "response undefined"; + } + + async getAllTxByKey( + key: string, + api: FabricApi, + netwokDetails: FabricNetworkDetails, + ): Promise { + const response = await api.runTransactionV1({ + signingCredential: netwokDetails.signingCredential, + channelName: netwokDetails.channelName, + contractName: netwokDetails.contractName, + methodName: "GetAllTxByKey", + invocationType: FabricContractInvocationType.Call, + params: [key], + } as RunTransactionRequest); + + if (response != undefined) { + return this.txsStringToTxs(response.data.functionOutput); + } + + return []; + } + + // Receive transactions in string format and parses to Transaction [] + txsStringToTxs(txString: string): Transaction[] { + const transactions: Transaction[] = []; + const txs = JSON.parse(txString); + for (const tx of txs) { + const txId = tx.value.txId; + const ts = tx.value.timestamp.seconds; + transactions.push( + new Transaction( + txId, + ts, + new TransactionProof(new Proof({ creator: "" })), + ), + ); + } + return transactions.reverse(); + } +} diff --git a/packages/cactus-plugin-bungee/src/main/typescript/utils.ts b/packages/cactus-plugin-bungee/src/main/typescript/utils.ts index 57d2c8b9ef8..cdf3c7297d3 100644 --- a/packages/cactus-plugin-bungee/src/main/typescript/utils.ts +++ b/packages/cactus-plugin-bungee/src/main/typescript/utils.ts @@ -1,5 +1,3 @@ -import { Transaction } from "./view-creation/transaction"; - export class Utils { static bufArray2HexStr(array: Uint8Array): string { return Buffer.from(array).toString("hex"); @@ -21,21 +19,4 @@ export class Utils { const data = fs.readFileSync(fileName, "utf8"); return data; } - - // Receive transactions in string format and parses to Transaction [] - static txsStringToTxs(txString: string): Transaction[] { - // eslint-disable-next-line prefer-const - let transactions: Transaction[] = []; - - const txs = JSON.parse(txString); - - for (const tx of txs) { - const txId = tx.value.txId; - // const ts = tx.value.timestamp.seconds + "." + tx.value.timestamp.nanos; - const ts = tx.value.timestamp.seconds; - transactions.push(new Transaction(txId, ts)); - } - - return transactions; - } } diff --git a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/proof.ts b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/proof.ts index c3d493f0450..bb594409859 100644 --- a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/proof.ts +++ b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/proof.ts @@ -1,20 +1,24 @@ export class Proof { - private mspid: string; - private endorserID: string; - private signature: string; + private creator: string; + private mspid?: string; + private signature?: string; - constructor(mspid: string, endorserID: string, signature: string) { - this.mspid = mspid; - this.endorserID = endorserID; - this.signature = signature; + constructor(settings: { + creator: string; + mspid?: string; + signature?: string; + }) { + this.creator = settings.creator; + this.mspid = settings.mspid ? settings.mspid : "undefined"; + this.signature = settings.signature ? settings.signature : "undefined"; } public printEndorsement(): string { return ( "Endorsement: \n " + - this.mspid + + this.creator + " \n " + - this.endorserID + + this.mspid + " \n " + this.signature ); @@ -22,23 +26,23 @@ export class Proof { public getEndorsementJson(): string { const proof = { + creator: this.creator, mspid: this.mspid, - endorserID: this.endorserID, signature: this.signature, }; // JSON.stringify(Array.from(endors.entries())); return JSON.stringify(proof); } - public getMspid(): string { - return this.mspid; + public getCreator(): string { + return this.creator; } - public getEndorserID(): string { - return this.endorserID; + public getMspid(): string | undefined { + return this.mspid; } - public getSignature(): string { + public getSignature(): string | undefined { return this.signature; } } diff --git a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/snapshot.ts b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/snapshot.ts index dd9c30c2a64..e5335d0ab97 100644 --- a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/snapshot.ts +++ b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/snapshot.ts @@ -3,39 +3,82 @@ import { State } from "./state"; export class Snapshot { private id: string; private participant; - private version: number; private stateBins: State[]; //set of state bins + private tI: string = ""; + private tF: string = ""; constructor(id: string, participant: string, stateBins: State[]) { this.id = id; this.participant = participant; - this.version = 1; this.stateBins = stateBins; } - private getVersion(): number { - return this.version; - } - private getId(): string { return this.id; } + public getTI() { + return this.tI; + } + public getTF() { + return this.tF; + } + public setTF(tF: string) { + this.tF = tF; + } + + public setTI(tI: string) { + this.tI = tI; + } + + public update_TI_TF() { + let ti = 999999999999999; + let tf = 0; + for (const bin of this.stateBins) { + const tI = Number(bin.getInitialTime()); + const tF = Number(bin.getFinalTime()); + if (tf < tF) { + tf = tF; + } + if (ti > tI) { + ti = tI; + } + } + this.tF = tf.toString(); + this.tI = ti.toString(); + } + public pruneStates(tI: string, tF: string): void { for (const state of this.stateBins) { state.pruneState(tI, tF); } } - public getLedgerStates(): State[] { + public getStateBins() { return this.stateBins; } + public filterStates(tI: string, tF: string): void { + const finalT = parseInt(tF); + const initialT = parseInt(tI); + const stateBins: State[] = []; + for (const state of this.stateBins) { + //FIXME string to uint ?? :) + if ( + parseInt(state.getInitialTime()) > finalT || + parseInt(state.getFinalTime()) < initialT + ) { + continue; + } + stateBins.push(state); + } + this.stateBins = stateBins; + } + public getSnapshotJson(): string { const snapshotJson = { id: this.id, participant: this.participant, - version: this.version, stateBins: this.stateBins, }; diff --git a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/state-proof.ts b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/state-proof.ts new file mode 100644 index 00000000000..0854254a88c --- /dev/null +++ b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/state-proof.ts @@ -0,0 +1,32 @@ +export interface Block { + blockHash: string; + blockCreator: string; + blockSigners: string[]; +} + +export class StateProof { + private stateID: string; + private value: string; + private blocks: Block[]; + private version: number; + + constructor(value: string, version: number, stateID: string) { + this.blocks = []; + this.value = value; + this.version = version; + this.stateID = stateID; + } + + public getValue() { + return this.value; + } + public getVersion() { + return this.version; + } + public getStateID() { + return this.stateID; + } + public addBlock(block: Block) { + this.blocks.push(block); + } +} diff --git a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/state.ts b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/state.ts index aa396b474d8..9f56c02630f 100644 --- a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/state.ts +++ b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/state.ts @@ -1,25 +1,42 @@ +import { StateProof } from "./state-proof"; import { Transaction } from "./transaction"; export class State { private id: string; private version: number; - private values: string[]; //set of state bins + private values: string[]; private transactions: Transaction[]; + private stateProof: StateProof[] = []; constructor(id: string, stateBins: string[], transactions: Transaction[]) { this.id = id; - this.version = stateBins.length; + this.version = transactions.length; this.values = stateBins; this.transactions = transactions; } + public getStateProof(): StateProof[] { + return this.stateProof; + } + public getId(): string { + return this.id; + } + + public getValues(): string[] { + return this.values; + } + + public setStateProof(proof: StateProof[]) { + this.stateProof = proof; + } + public getStateJson(): string { const txs: string[] = []; const txEndorsements: string[] = []; for (const tx of this.transactions) { txs.push(tx.getTxJson()); - txEndorsements.push(tx.getTxProofs()); + txEndorsements.push(JSON.stringify(tx.getProof())); } const jsonSnap = { @@ -33,6 +50,10 @@ export class State { return JSON.stringify(jsonSnap); } + public getTransactions() { + return this.transactions; + } + //JUST FOR TESTING public getTimeForTxN(index: number): string { return this.transactions[index].getTimeStamp(); @@ -40,34 +61,37 @@ export class State { public getInitialTime(): string { if (this.transactions.length >= 1) { - return this.transactions[this.transactions.length - 1].getTimeStamp(); + return this.transactions[0].getTimeStamp(); } return ""; } public getFinalTime(): string { if (this.transactions.length >= 1) { - return this.transactions[0].getTimeStamp(); + return this.transactions[this.transactions.length - 1].getTimeStamp(); } return ""; } + public getValue(): string { + return this.values[this.values.length - 1]; + } - private getVersion(): string { + public getVersion(): string { return this.version.toString(); } - public pruneState(tsStart: string, tsEnd: string): void { - const tsStartNum = parseInt(tsStart); - const tsEndNum = parseInt(tsEnd); + public pruneState(tI: string, tF: string): void { + const initialT = parseInt(tI); + const finalT = parseInt(tF); // eslint-disable-next-line prefer-const this.transactions.forEach((element, index) => { if ( - parseInt(element.getTimeStamp()) < tsStartNum || - parseInt(element.getTimeStamp()) > tsEndNum + parseInt(element.getTimeStamp()) < initialT || + parseInt(element.getTimeStamp()) > finalT ) { - this.version = this.version - 1; + //this.version = this.version - 1; this.transactions.splice(index, 1); //Remove tx - this.values.splice(index, 1); //Remove state of tx + this.values?.splice(index, 1); //Remove state of tx } }); } diff --git a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/transaction-proof.ts b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/transaction-proof.ts new file mode 100644 index 00000000000..f770876c252 --- /dev/null +++ b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/transaction-proof.ts @@ -0,0 +1,35 @@ +import { Proof } from "./proof"; + +export class TransactionProof { + private creator: Proof; + private endorsers?: Proof[] = []; + + constructor(creator: Proof) { + this.creator = creator; + } + + public addEndorser(endorser: Proof) { + this.endorsers?.push(endorser); + } + + public printEndorsement(): string { + return "Endorsement: \n " + this.creator + " \n " + this.endorsers; + } + + public getEndorsementJson(): string { + const proof = { + creator: this.creator, + endorsers: this.endorsers, + }; + // JSON.stringify(Array.from(endors.entries())); + return JSON.stringify(proof); + } + + public getCreator(): Proof { + return this.creator; + } + + public getEndorsements(): Proof[] | undefined { + return this.endorsers; + } +} diff --git a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/transaction.ts b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/transaction.ts index c6dd5c52888..34473cb26ce 100644 --- a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/transaction.ts +++ b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/transaction.ts @@ -1,35 +1,67 @@ import { Proof } from "./proof"; +import { TransactionProof } from "./transaction-proof"; export class Transaction { private id: string; private timeStamp: string; - private proofs: Proof[]; + private proof: TransactionProof; + private stateId?: string; + private payload?: string; + private target?: string; + //private blockN?: number; - constructor(id: string, timeStamp: string) { + constructor(id: string, timeStamp: string, proof: TransactionProof) { this.id = id; this.timeStamp = timeStamp; - this.proofs = []; + this.proof = proof; } public printTransaction(): string { return "Transaction: \n " + this.id + " \n " + this.timeStamp; } - public defineTxProofs(proofs: Proof[]): void { - this.proofs = proofs; + public addEndorser(endorser: Proof): void { + this.proof.addEndorser(endorser); } public getId(): string { return this.id; } + //public getBlockN() { + // return this.blockN; + //} + public getTarget() { + return this.target; + } + public getPayload() { + return this.payload; + } + public getStateId() { + return this.stateId; + } + + //public setBlockN(n: number) { + // this.blockN = n; + //} + + public setTarget(target: string) { + this.target = target; + } + public setPayload(payload: string) { + this.payload = payload; + } + public setStateId(stateId: string) { + this.stateId = stateId; + } + public getTxJson(): string { const tx = { Id: this.id, TimeStamp: this.timeStamp }; return JSON.stringify(tx); } - public getTxProofs(): string { - const txProofs = { id: this.id, proofs: this.proofs }; - return JSON.stringify(txProofs); + public getProof(): TransactionProof { + //const txProofs = { id: this.id, proof: this.proof }; + return this.proof; } public getTimeStamp(): string { diff --git a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/view.ts b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/view.ts index 695d0911e83..99fe1b693ed 100644 --- a/packages/cactus-plugin-bungee/src/main/typescript/view-creation/view.ts +++ b/packages/cactus-plugin-bungee/src/main/typescript/view-creation/view.ts @@ -1,23 +1,27 @@ +import { v4 as uuidV4 } from "uuid"; import { Snapshot } from "./snapshot"; export class View { - private snapshot; + private key: string; + private snapshot: Snapshot; private tI; private tF; - constructor(tI: string, tF: string, snapshot: Snapshot) { + constructor( + tI: string, + tF: string, + snapshot: Snapshot, + id: string | undefined, + ) { + this.key = id ? id : uuidV4(); // FIXME receive as input maybe this.tI = tI; this.tF = tF; this.snapshot = snapshot; - this.pruneSnapshot(); + snapshot.pruneStates(this.tI, this.tF); } - - private pruneSnapshot(): void { - if (this.tI != "0" && this.tF != "0") { - this.snapshot.pruneStates(this.tI, this.tF); - } + public getKey() { + return this.key; } - public getViewStr(): string { const viewStr = { tI: this.tI, diff --git a/packages/cactus-plugin-bungee/src/main/typescript/web-services/client-endpoint.ts b/packages/cactus-plugin-bungee/src/main/typescript/web-services/client-endpoint.ts index 4df190f1f9c..486151c5dc9 100644 --- a/packages/cactus-plugin-bungee/src/main/typescript/web-services/client-endpoint.ts +++ b/packages/cactus-plugin-bungee/src/main/typescript/web-services/client-endpoint.ts @@ -89,8 +89,8 @@ export class ClientEndpointV1 implements IWebServiceEndpoint { const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; this.log.debug(reqTag); try { - //await this.options.bungee.onCreateView(req.body); - res.status(200).json("OK"); + const view = await this.options.bungee.onCreateView(req.body); + res.status(200).json(view); } catch (ex) { this.log.error(`Crash while serving ${reqTag}`, ex); res.status(500).json({ diff --git a/packages/cactus-plugin-bungee/src/test/typescript/fabric-contracts/simple-asset/chaincode-typescript/package.json b/packages/cactus-plugin-bungee/src/test/typescript/fabric-contracts/simple-asset/chaincode-typescript/package.json index c56da8ab5ec..be0854f059d 100644 --- a/packages/cactus-plugin-bungee/src/test/typescript/fabric-contracts/simple-asset/chaincode-typescript/package.json +++ b/packages/cactus-plugin-bungee/src/test/typescript/fabric-contracts/simple-asset/chaincode-typescript/package.json @@ -37,7 +37,7 @@ "sinon-chai": "3.7.0", "ts-node": "7.0.1", "tslint": "5.20.1", - "typescript": "3.9.10" + "typescript": "5.3.3" }, "nyc": { "extension": [ diff --git a/packages/cactus-plugin-bungee/src/test/typescript/integration/besu-test-basic.test.ts b/packages/cactus-plugin-bungee/src/test/typescript/integration/besu-test-basic.test.ts new file mode 100644 index 00000000000..fc7ac126c13 --- /dev/null +++ b/packages/cactus-plugin-bungee/src/test/typescript/integration/besu-test-basic.test.ts @@ -0,0 +1,352 @@ +import { + IListenOptions, + LogLevelDesc, + LoggerProvider, + Secp256k1Keys, + Servers, +} from "@hyperledger/cactus-common"; +import "jest-extended"; +import LockAssetContractJson from "../solidity/lock-asset-contract/LockAsset.json"; + +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; +import bodyParser from "body-parser"; + +import http, { Server } from "http"; +import { Server as SocketIoServer } from "socket.io"; + +import express from "express"; +import { AddressInfo } from "net"; +import { v4 as uuidv4 } from "uuid"; +import { + BesuTestLedger, + pruneDockerAllIfGithubAction, + Containers, +} from "@hyperledger/cactus-test-tooling"; +import { Constants } from "@hyperledger/cactus-core-api"; +import { + Web3SigningCredentialType, + PluginLedgerConnectorBesu, + EthContractInvocationType, + ReceiptType, + IPluginLedgerConnectorBesuOptions, + Web3SigningCredential, +} from "@hyperledger/cactus-plugin-ledger-connector-besu"; +import Web3 from "web3"; +import { Account } from "web3-core"; +import { + PluginBUNGEE, + IPluginBUNGEEOptions, +} from "../../../main/typescript/plugin-bungee"; + +import { + BesuNetworkDetails, + StrategyBesu, +} from "../../../main/typescript/strategy/strategy-besu"; + +const logLevel: LogLevelDesc = "INFO"; + +let besuLedger: BesuTestLedger; +let contractName: string; +//let besuServer: Server; + +let rpcApiHttpHost: string; +let rpcApiWsHost: string; +let web3: Web3; +let firstHighNetWorthAccount: string; +let connector: PluginLedgerConnectorBesu; +let besuKeyPair: { privateKey: string }; +let testEthAccount: Account; +const BESU_ASSET_ID = uuidv4(); + +const log = LoggerProvider.getOrCreate({ + level: logLevel, + label: "BUNGEE dummy testing", +}); +let besuPath: string; +let pluginBungeeOptions: IPluginBUNGEEOptions; +let besuServer: Server; + +let bungeeSigningCredential: Web3SigningCredential; +let bungeeKeychainId: string; +let bungeeContractAddress: string; + +let keychainPlugin: PluginKeychainMemory; + +beforeAll(async () => { + pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + log.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); + + { + besuLedger = new BesuTestLedger({ + logLevel, + emitContainerLogs: true, + envVars: ["BESU_NETWORK=dev"], + }); + await besuLedger.start(); + + rpcApiHttpHost = await besuLedger.getRpcApiHttpHost(); + rpcApiWsHost = await besuLedger.getRpcApiWsHost(); + web3 = new Web3(rpcApiHttpHost); + firstHighNetWorthAccount = besuLedger.getGenesisAccountPubKey(); + + testEthAccount = await besuLedger.createEthTestAccount(); + + besuKeyPair = { + privateKey: besuLedger.getGenesisAccountPrivKey(), + }; + + contractName = "LockAsset"; + + const keychainEntryValue = besuKeyPair.privateKey; + const keychainEntryKey = uuidv4(); + keychainPlugin = new PluginKeychainMemory({ + instanceId: uuidv4(), + keychainId: uuidv4(), + + backend: new Map([[keychainEntryKey, keychainEntryValue]]), + logLevel, + }); + keychainPlugin.set( + LockAssetContractJson.contractName, + JSON.stringify(LockAssetContractJson), + ); + + const pluginRegistry = new PluginRegistry({ + plugins: [keychainPlugin], + }); + + const options: IPluginLedgerConnectorBesuOptions = { + instanceId: uuidv4(), + rpcApiHttpHost, + rpcApiWsHost, + pluginRegistry, + logLevel, + }; + connector = new PluginLedgerConnectorBesu(options); + pluginRegistry.add(connector); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + besuServer = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 4000, + server: besuServer, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + const { address, port } = addressInfo; + + await connector.getOrCreateWebServices(); + const wsApi = new SocketIoServer(besuServer, { + path: Constants.SocketIoConnectionPathV1, + }); + await connector.registerWebServices(expressApp, wsApi); + besuPath = `http://${address}:${port}`; + + await connector.transact({ + web3SigningCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + consistencyStrategy: { + blockConfirmations: 0, + receiptType: ReceiptType.NodeTxPoolAck, + }, + transactionConfig: { + from: firstHighNetWorthAccount, + to: testEthAccount.address, + value: 10e9, + gas: 1000000, + }, + }); + const balance = await web3.eth.getBalance(testEthAccount.address); + expect(balance).toBeTruthy(); + expect(parseInt(balance, 10)).toBeGreaterThan(10e9); + + log.info("Connector initialized"); + + const deployOut = await connector.deployContract({ + keychainId: keychainPlugin.getKeychainId(), + contractName: LockAssetContractJson.contractName, + contractAbi: LockAssetContractJson.abi, + constructorArgs: [], + web3SigningCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + bytecode: LockAssetContractJson.bytecode, + gas: 1000000, + }); + expect(deployOut).toBeTruthy(); + expect(deployOut.transactionReceipt).toBeTruthy(); + expect(deployOut.transactionReceipt.contractAddress).toBeTruthy(); + log.info("Contract Deployed successfully"); + + const res = await connector.invokeContract({ + contractName, + keychainId: keychainPlugin.getKeychainId(), + invocationType: EthContractInvocationType.Send, + methodName: "createAsset", + params: [BESU_ASSET_ID, 19], + signingCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + gas: 1000000, + }); + expect(res).toBeTruthy(); + expect(res.success).toBeTruthy(); + + const res3 = await connector.invokeContract({ + contractName, + keychainId: keychainPlugin.getKeychainId(), + invocationType: EthContractInvocationType.Call, + methodName: "getAsset", + params: [BESU_ASSET_ID], + signingCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + gas: 1000000, + }); + expect(res3).toBeTruthy(); + expect(res3.success).toBeTruthy(); + expect(res3.callOutput.toString()).toBeTruthy(); + + bungeeSigningCredential = { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }; + bungeeKeychainId = keychainPlugin.getKeychainId(); + + bungeeContractAddress = deployOut.transactionReceipt + .contractAddress as string; + + pluginBungeeOptions = { + keyPair: Secp256k1Keys.generateKeyPairsBuffer(), + instanceId: uuidv4(), + logLevel, + }; + } +}); + +test("test creation of views for different timeframes and states", async () => { + const bungee = new PluginBUNGEE(pluginBungeeOptions); + const strategy = "BESU"; + bungee.addStrategy(strategy, new StrategyBesu("INFO")); + const networkDetails: BesuNetworkDetails = { + signingCredential: bungeeSigningCredential, + contractName, + connectorApiPath: besuPath, + keychainId: bungeeKeychainId, + contractAddress: bungeeContractAddress, + participant: firstHighNetWorthAccount, + }; + + const snapshot = await bungee.generateSnapshot([], strategy, networkDetails); + const view = bungee.generateView(snapshot, "0", "9999999999999", undefined); + //expect to return a view + expect(view.view).toBeTruthy(); + expect(view.signature).toBeTruthy(); + + //expect the view to have capture the new asset BESU_ASSET_ID, and attributes to match + expect(snapshot.getStateBins().length).toEqual(1); + expect(snapshot.getStateBins()[0].getId()).toEqual(BESU_ASSET_ID); + expect(snapshot.getStateBins()[0].getTransactions().length).toEqual(1); + + const view1 = bungee.generateView(snapshot, "0", "9999", undefined); + + //expects nothing to limit time of 9999 + expect(view1.view).toBeUndefined(); + expect(view1.signature).toBeUndefined(); + + //changing BESU_ASSET_ID value + const lockAsset = await connector.invokeContract({ + contractName, + keychainId: keychainPlugin.getKeychainId(), + invocationType: EthContractInvocationType.Send, + methodName: "lockAsset", + params: [BESU_ASSET_ID], + signingCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + gas: 1000000, + }); + expect(lockAsset).not.toBeUndefined(); + expect(lockAsset.success).toBeTrue(); + + //creating new asset + const new_asset_id = uuidv4(); + const depNew = await connector.invokeContract({ + contractName, + keychainId: keychainPlugin.getKeychainId(), + invocationType: EthContractInvocationType.Send, + methodName: "createAsset", + params: [new_asset_id, 10], + signingCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + gas: 1000000, + }); + expect(depNew).not.toBeUndefined(); + expect(depNew.success).toBeTrue(); + + const snapshot1 = await bungee.generateSnapshot([], strategy, networkDetails); + const view2 = bungee.generateView(snapshot1, "0", "9999999999999", undefined); + //expect to return a view + expect(view2.view).toBeTruthy(); + expect(view2.signature).toBeTruthy(); + + const stateBins = snapshot1.getStateBins(); + expect(stateBins.length).toEqual(2); //expect to have captured state for both assets + + const bins = [stateBins[0].getId(), stateBins[1].getId()]; + + //checks if values match: + // - new value of BESU_ASSET_ID state in new snapshot different than value from old snapshot) + // - successfully captured transaction that created the new asset + if (bins[0] === BESU_ASSET_ID) { + expect(snapshot1.getStateBins()[0].getTransactions().length).toEqual(2); + expect(snapshot1.getStateBins()[0].getValue()).not.toEqual( + snapshot.getStateBins()[0].getValue(), + ); + expect(snapshot1.getStateBins()[1].getTransactions().length).toEqual(1); + } else { + expect(snapshot1.getStateBins()[0].getTransactions().length).toEqual(1); + expect(snapshot1.getStateBins()[1].getTransactions().length).toEqual(2); + expect(snapshot1.getStateBins()[1].getValue()).not.toEqual( + snapshot.getStateBins()[0].getValue(), + ); + } +}); + +afterAll(async () => { + await Servers.shutdown(besuServer); + await besuLedger.stop(); + await besuLedger.destroy(); + + await pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + log.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); +}); diff --git a/packages/cactus-plugin-bungee/src/test/typescript/integration/besu-test-pruning.test.ts b/packages/cactus-plugin-bungee/src/test/typescript/integration/besu-test-pruning.test.ts new file mode 100644 index 00000000000..d89a52bdeb1 --- /dev/null +++ b/packages/cactus-plugin-bungee/src/test/typescript/integration/besu-test-pruning.test.ts @@ -0,0 +1,323 @@ +import { + IListenOptions, + LogLevelDesc, + LoggerProvider, + Secp256k1Keys, + Servers, +} from "@hyperledger/cactus-common"; +import "jest-extended"; +import LockAssetContractJson from "../solidity/lock-asset-contract/LockAsset.json"; + +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; +import bodyParser from "body-parser"; + +import http, { Server } from "http"; +import { Server as SocketIoServer } from "socket.io"; + +import express from "express"; +import { AddressInfo } from "net"; +import { v4 as uuidv4 } from "uuid"; +import { + BesuTestLedger, + pruneDockerAllIfGithubAction, + Containers, +} from "@hyperledger/cactus-test-tooling"; +import { Constants } from "@hyperledger/cactus-core-api"; +import { + Web3SigningCredentialType, + PluginLedgerConnectorBesu, + EthContractInvocationType, + ReceiptType, + IPluginLedgerConnectorBesuOptions, + Web3SigningCredential, +} from "@hyperledger/cactus-plugin-ledger-connector-besu"; +import Web3 from "web3"; +import { Account } from "web3-core"; +import { + PluginBUNGEE, + IPluginBUNGEEOptions, +} from "../../../main/typescript/plugin-bungee"; + +import { + BesuNetworkDetails, + StrategyBesu, +} from "../../../main/typescript/strategy/strategy-besu"; + +const logLevel: LogLevelDesc = "INFO"; + +let besuLedger: BesuTestLedger; +let contractName: string; +//let besuServer: Server; + +let rpcApiHttpHost: string; +let rpcApiWsHost: string; +let web3: Web3; +let firstHighNetWorthAccount: string; +let connector: PluginLedgerConnectorBesu; +let besuKeyPair: { privateKey: string }; +let testEthAccount: Account; +const BESU_ASSET_ID = uuidv4(); + +const log = LoggerProvider.getOrCreate({ + level: logLevel, + label: "BUNGEE dummy testing", +}); +let besuPath: string; +let pluginBungeeOptions: IPluginBUNGEEOptions; +let besuServer: Server; + +let bungeeSigningCredential: Web3SigningCredential; +let bungeeKeychainId: string; +let bungeeContractAddress: string; + +let keychainPlugin: PluginKeychainMemory; + +beforeAll(async () => { + pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + log.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); + + { + besuLedger = new BesuTestLedger({ + logLevel, + emitContainerLogs: true, + envVars: ["BESU_NETWORK=dev"], + }); + await besuLedger.start(); + + rpcApiHttpHost = await besuLedger.getRpcApiHttpHost(); + rpcApiWsHost = await besuLedger.getRpcApiWsHost(); + web3 = new Web3(rpcApiHttpHost); + firstHighNetWorthAccount = besuLedger.getGenesisAccountPubKey(); + + testEthAccount = await besuLedger.createEthTestAccount(); + + besuKeyPair = { + privateKey: besuLedger.getGenesisAccountPrivKey(), + }; + + contractName = "LockAsset"; + + const keychainEntryValue = besuKeyPair.privateKey; + const keychainEntryKey = uuidv4(); + keychainPlugin = new PluginKeychainMemory({ + instanceId: uuidv4(), + keychainId: uuidv4(), + + backend: new Map([[keychainEntryKey, keychainEntryValue]]), + logLevel, + }); + keychainPlugin.set( + LockAssetContractJson.contractName, + JSON.stringify(LockAssetContractJson), + ); + + const pluginRegistry = new PluginRegistry({ + plugins: [keychainPlugin], + }); + + const options: IPluginLedgerConnectorBesuOptions = { + instanceId: uuidv4(), + rpcApiHttpHost, + rpcApiWsHost, + pluginRegistry, + logLevel, + }; + connector = new PluginLedgerConnectorBesu(options); + pluginRegistry.add(connector); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + besuServer = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 4000, + server: besuServer, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + const { address, port } = addressInfo; + + await connector.getOrCreateWebServices(); + const wsApi = new SocketIoServer(besuServer, { + path: Constants.SocketIoConnectionPathV1, + }); + await connector.registerWebServices(expressApp, wsApi); + besuPath = `http://${address}:${port}`; + + await connector.transact({ + web3SigningCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + consistencyStrategy: { + blockConfirmations: 0, + receiptType: ReceiptType.NodeTxPoolAck, + }, + transactionConfig: { + from: firstHighNetWorthAccount, + to: testEthAccount.address, + value: 10e9, + gas: 1000000, + }, + }); + const balance = await web3.eth.getBalance(testEthAccount.address); + expect(balance).toBeTruthy(); + expect(parseInt(balance, 10)).toBeGreaterThan(10e9); + + log.info("Connector initialized"); + + const deployOut = await connector.deployContract({ + keychainId: keychainPlugin.getKeychainId(), + contractName: LockAssetContractJson.contractName, + contractAbi: LockAssetContractJson.abi, + constructorArgs: [], + web3SigningCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + bytecode: LockAssetContractJson.bytecode, + gas: 1000000, + }); + expect(deployOut).toBeTruthy(); + expect(deployOut.transactionReceipt).toBeTruthy(); + expect(deployOut.transactionReceipt.contractAddress).toBeTruthy(); + log.info("Contract Deployed successfully"); + + const res = await connector.invokeContract({ + contractName, + keychainId: keychainPlugin.getKeychainId(), + invocationType: EthContractInvocationType.Send, + methodName: "createAsset", + params: [BESU_ASSET_ID, 19], + signingCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + gas: 1000000, + }); + expect(res).toBeTruthy(); + expect(res.success).toBeTruthy(); + + const res3 = await connector.invokeContract({ + contractName, + keychainId: keychainPlugin.getKeychainId(), + invocationType: EthContractInvocationType.Call, + methodName: "getAsset", + params: [BESU_ASSET_ID], + signingCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + gas: 1000000, + }); + expect(res3).toBeTruthy(); + expect(res3.success).toBeTruthy(); + expect(res3.callOutput.toString()).toBeTruthy(); + + bungeeSigningCredential = { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }; + bungeeKeychainId = keychainPlugin.getKeychainId(); + + bungeeContractAddress = deployOut.transactionReceipt + .contractAddress as string; + + pluginBungeeOptions = { + keyPair: Secp256k1Keys.generateKeyPairsBuffer(), + instanceId: uuidv4(), + logLevel, + }; + } +}); + +test("test creation of views for specific timeframes", async () => { + const bungee = new PluginBUNGEE(pluginBungeeOptions); + const strategy = "BESU"; + bungee.addStrategy(strategy, new StrategyBesu("INFO")); + const netwokDetails: BesuNetworkDetails = { + signingCredential: bungeeSigningCredential, + contractName, + connectorApiPath: besuPath, + keychainId: bungeeKeychainId, + contractAddress: bungeeContractAddress, + participant: firstHighNetWorthAccount, + }; + + const snapshot = await bungee.generateSnapshot([], strategy, netwokDetails); + const view = bungee.generateView(snapshot, "0", "9999999999999", undefined); + + //expect to return a view + expect(view.view).toBeTruthy(); + expect(view.signature).toBeTruthy(); + + //expect the view to have capture the new asset BESU_ASSET_ID, and attributes to match + expect(snapshot.getStateBins().length).toEqual(1); + expect(snapshot.getStateBins()[0].getId()).toEqual(BESU_ASSET_ID); + expect(snapshot.getStateBins()[0].getTransactions().length).toEqual(1); + + //changing BESU_ASSET_ID value + const lockAsset = await connector.invokeContract({ + contractName, + keychainId: keychainPlugin.getKeychainId(), + invocationType: EthContractInvocationType.Send, + methodName: "lockAsset", + params: [BESU_ASSET_ID], + signingCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + gas: 1000000, + }); + expect(lockAsset).not.toBeUndefined(); + expect(lockAsset.success).toBeTrue(); + + const snapshot1 = await bungee.generateSnapshot([], strategy, netwokDetails); + + //tI is the time of the first transaction + 1 + const tI = ( + parseInt(snapshot.getStateBins()[0].getTransactions()[0].getTimeStamp()) + 1 + ).toString(); + + const view1 = bungee.generateView(snapshot1, tI, "9999999999999", undefined); + + //expect to return a view + expect(view1.view).toBeTruthy(); + expect(view1.signature).toBeTruthy(); + + expect(snapshot1.getStateBins().length).toEqual(1); + expect(snapshot1.getStateBins()[0].getId()).toEqual(BESU_ASSET_ID); + //expect the view to not include first transaction (made before tI) + expect(snapshot1.getStateBins()[0].getTransactions().length).toEqual(1); + //expect old and new snapshot state values to differ + expect(snapshot1.getStateBins()[0].getValue()).not.toEqual( + snapshot.getStateBins()[0].getValue(), + ); +}); + +afterAll(async () => { + await Servers.shutdown(besuServer); + await besuLedger.stop(); + await besuLedger.destroy(); + + await pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + log.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); +}); diff --git a/packages/cactus-plugin-bungee/src/test/typescript/integration/bungee-api-test.test.ts b/packages/cactus-plugin-bungee/src/test/typescript/integration/bungee-api-test.test.ts new file mode 100644 index 00000000000..145d6ac354b --- /dev/null +++ b/packages/cactus-plugin-bungee/src/test/typescript/integration/bungee-api-test.test.ts @@ -0,0 +1,610 @@ +import { + IListenOptions, + LogLevelDesc, + LoggerProvider, + Secp256k1Keys, + Servers, +} from "@hyperledger/cactus-common"; +import "jest-extended"; +import LockAssetContractJson from "../solidity/lock-asset-contract/LockAsset.json"; + +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; +import bodyParser from "body-parser"; + +import http, { Server } from "http"; +import { Server as SocketIoServer } from "socket.io"; +import fs from "fs-extra"; +import express from "express"; +import { AddressInfo } from "net"; +import { v4 as uuidv4 } from "uuid"; +import { + BesuTestLedger, + pruneDockerAllIfGithubAction, + Containers, + FabricTestLedgerV1, + DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + DEFAULT_FABRIC_2_AIO_IMAGE_VERSION, + DEFAULT_FABRIC_2_AIO_FABRIC_VERSION, +} from "@hyperledger/cactus-test-tooling"; +import { Configuration, Constants } from "@hyperledger/cactus-core-api"; +import { + Web3SigningCredentialType, + PluginLedgerConnectorBesu, + EthContractInvocationType, + ReceiptType, + IPluginLedgerConnectorBesuOptions, + Web3SigningCredential, +} from "@hyperledger/cactus-plugin-ledger-connector-besu"; +import Web3 from "web3"; +import { Account } from "web3-core"; +import { + PluginBUNGEE, + IPluginBUNGEEOptions, +} from "../../../main/typescript/plugin-bungee"; +import { DefaultApi as BungeeApi } from "../../../main/typescript/generated/openapi/typescript-axios/api"; +import { + FabricSigningCredential, + PluginLedgerConnectorFabric, + DefaultApi as FabricApi, + DefaultEventHandlerStrategy, + IPluginLedgerConnectorFabricOptions, + ChainCodeProgrammingLanguage, + FabricContractInvocationType, + FileBase64, +} from "@hyperledger/cactus-plugin-ledger-connector-fabric"; +import path from "path"; +import { DiscoveryOptions } from "fabric-network"; +import { + FabricNetworkDetails, + StrategyFabric, +} from "../../../main/typescript/strategy/strategy-fabric"; +import { + BesuNetworkDetails, + StrategyBesu, +} from "../../../main/typescript/strategy/strategy-besu"; + +const logLevel: LogLevelDesc = "INFO"; + +let besuLedger: BesuTestLedger; +let besuContractName: string; +let besuPath: string; +let besuServer: Server; +let besuConnector: PluginLedgerConnectorBesu; +let besuKeyPair: { privateKey: string }; +let testEthAccount: Account; +let firstHighNetWorthAccount: string; +let besuKeychainPlugin: PluginKeychainMemory; +let besuSigningCredential: Web3SigningCredential; +let besuContractAddress: string; + +let rpcApiHttpHost: string; +let rpcApiWsHost: string; +let web3: Web3; +const BESU_ASSET_ID = uuidv4(); + +const log = LoggerProvider.getOrCreate({ + level: logLevel, + label: "BUNGEE dummy testing", +}); + +let fabricKeychainPlugin: PluginKeychainMemory; +let configFabric: Configuration; +let fabricLedger: FabricTestLedgerV1; +let fabricSigningCredential: FabricSigningCredential; +let fabricConnector: PluginLedgerConnectorFabric; +let fabricContractName: string; +let fabricChannelName: string; +let fabricPath: string; +let fabricApi: FabricApi; +let fabricServer: Server; +const FABRIC_ASSET_ID = uuidv4(); + +let pluginBungeeOptions: IPluginBUNGEEOptions; +let bungeeServer: Server; + +const BESU_STRATEGY = "BESU"; +const FABRIC_STRATEGY = "FABRIC"; + +beforeAll(async () => { + pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + log.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); + + { + log.info(await setupFabricTestLedger()); + log.info(await setupBesuTestLedger()); + } +}); + +test("tests bungee api using different strategies", async () => { + pluginBungeeOptions = { + keyPair: Secp256k1Keys.generateKeyPairsBuffer(), + instanceId: uuidv4(), + logLevel, + }; + const bungee = new PluginBUNGEE(pluginBungeeOptions); + + //add both strategies to BUNGEE + bungee.addStrategy(FABRIC_STRATEGY, new StrategyFabric("INFO")); + bungee.addStrategy(BESU_STRATEGY, new StrategyBesu("INFO")); + + //store network details for both networks + const besuNetworkDetails: BesuNetworkDetails = { + signingCredential: besuSigningCredential, + contractName: besuContractName, + connectorApiPath: besuPath, + keychainId: besuKeychainPlugin.getKeychainId(), + contractAddress: besuContractAddress, + participant: firstHighNetWorthAccount, + }; + const fabricNetworkDetails: FabricNetworkDetails = { + connectorApiPath: fabricPath, + signingCredential: fabricSigningCredential, + channelName: fabricChannelName, + contractName: fabricContractName, + participant: "Org1MSP", + }; + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + bungeeServer = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 3000, + server: bungeeServer, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + const { address, port } = addressInfo; + + await bungee.getOrCreateWebServices(); + await bungee.registerWebServices(expressApp); + const bungeePath = `http://${address}:${port}`; + + const config = new Configuration({ basePath: bungeePath }); + const bungeeApi = new BungeeApi(config); + + //View creation for both networks, using the respective strategies + + const viewFabric = await bungeeApi.createViewV1({ + strategyId: FABRIC_STRATEGY, + networkDetails: fabricNetworkDetails, + }); + //expect to return a view + expect(viewFabric.status).toEqual(200); + expect(viewFabric.data.view).toBeTruthy(); + + const viewBesu = await bungeeApi.createViewV1({ + strategyId: BESU_STRATEGY, + networkDetails: besuNetworkDetails, + }); + //expect to return a view + expect(viewBesu.status).toEqual(200); + expect(viewBesu.data.view).toBeTruthy(); +}); + +afterAll(async () => { + await Servers.shutdown(besuServer); + await Servers.shutdown(fabricServer); + await Servers.shutdown(bungeeServer); + await besuLedger.stop(); + await besuLedger.destroy(); + await fabricLedger.stop(); + await fabricLedger.destroy(); + + await pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + log.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); +}); + +async function setupFabricTestLedger(): Promise { + const channelId = "mychannel"; + fabricChannelName = channelId; + + fabricLedger = new FabricTestLedgerV1({ + emitContainerLogs: true, + publishAllPorts: true, + imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + imageVersion: DEFAULT_FABRIC_2_AIO_IMAGE_VERSION, + envVars: new Map([["FABRIC_VERSION", DEFAULT_FABRIC_2_AIO_FABRIC_VERSION]]), + logLevel, + }); + await fabricLedger.start(); + log.info("Fabric Ledger started"); + + const connectionProfile = await fabricLedger.getConnectionProfileOrg1(); + expect(connectionProfile).not.toBeUndefined(); + + const enrollAdminOut = await fabricLedger.enrollAdmin(); + const adminWallet = enrollAdminOut[1]; + const [userIdentity] = await fabricLedger.enrollUser(adminWallet); + const sshConfig = await fabricLedger.getSshConfig(); + + log.info("enrolled admin"); + + const keychainInstanceId = uuidv4(); + const keychainId = uuidv4(); + const keychainEntryKey = "user1"; + const keychainEntryValue = JSON.stringify(userIdentity); + + fabricKeychainPlugin = new PluginKeychainMemory({ + instanceId: keychainInstanceId, + keychainId, + logLevel, + backend: new Map([ + [keychainEntryKey, keychainEntryValue], + ["some-other-entry-key", "some-other-entry-value"], + ]), + }); + + const pluginRegistry = new PluginRegistry({ + plugins: [fabricKeychainPlugin], + }); + + const discoveryOptions: DiscoveryOptions = { + enabled: true, + asLocalhost: true, + }; + + // This is the directory structure of the Fabirc 2.x CLI container (fabric-tools image) + // const orgCfgDir = "/fabric-samples/test-network/organizations/"; + const orgCfgDir = + "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/"; + + // these below mirror how the fabric-samples sets up the configuration + const org1Env = { + CORE_LOGGING_LEVEL: "debug", + FABRIC_LOGGING_SPEC: "debug", + CORE_PEER_LOCALMSPID: "Org1MSP", + + ORDERER_CA: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + + FABRIC_CFG_PATH: "/etc/hyperledger/fabric", + CORE_PEER_TLS_ENABLED: "true", + CORE_PEER_TLS_ROOTCERT_FILE: `${orgCfgDir}peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt`, + CORE_PEER_MSPCONFIGPATH: `${orgCfgDir}peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp`, + CORE_PEER_ADDRESS: "peer0.org1.example.com:7051", + ORDERER_TLS_ROOTCERT_FILE: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + }; + + // these below mirror how the fabric-samples sets up the configuration + const org2Env = { + CORE_LOGGING_LEVEL: "debug", + FABRIC_LOGGING_SPEC: "debug", + CORE_PEER_LOCALMSPID: "Org2MSP", + + FABRIC_CFG_PATH: "/etc/hyperledger/fabric", + CORE_PEER_TLS_ENABLED: "true", + ORDERER_CA: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + + CORE_PEER_ADDRESS: "peer0.org2.example.com:9051", + CORE_PEER_MSPCONFIGPATH: `${orgCfgDir}peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp`, + CORE_PEER_TLS_ROOTCERT_FILE: `${orgCfgDir}peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt`, + ORDERER_TLS_ROOTCERT_FILE: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + }; + + const pluginOptions: IPluginLedgerConnectorFabricOptions = { + instanceId: uuidv4(), + dockerBinary: "/usr/local/bin/docker", + peerBinary: "/fabric-samples/bin/peer", + goBinary: "/usr/local/go/bin/go", + pluginRegistry, + cliContainerEnv: org1Env, + sshConfig, + logLevel: "INFO", + connectionProfile, + discoveryOptions, + eventHandlerOptions: { + strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, + commitTimeout: 300, + }, + }; + + fabricConnector = new PluginLedgerConnectorFabric(pluginOptions); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + fabricServer = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 4100, + server: fabricServer, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + const { address, port } = addressInfo; + + await fabricConnector.getOrCreateWebServices(); + await fabricConnector.registerWebServices(expressApp); + + log.info("Fabric Ledger connector check"); + + const apiUrl = `http://${address}:${port}`; + + fabricPath = apiUrl; + configFabric = new Configuration({ basePath: apiUrl }); + + fabricApi = new FabricApi(configFabric); + + fabricContractName = "basic-asset-transfer-2"; + const contractRelPath = + "../fabric-contracts/simple-asset/chaincode-typescript"; + const contractDir = path.join(__dirname, contractRelPath); + + // ├── package.json + // ├── src + // │ ├── assetTransfer.ts + // │ ├── asset.ts + // │ └── index.ts + // ├── tsconfig.json + // -------- + const sourceFiles: FileBase64[] = []; + { + const filename = "./tsconfig.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./package.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./index.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./asset.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./assetTransfer.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + + const res = await fabricApi.deployContractV1({ + channelId, + ccVersion: "1.0.0", + sourceFiles, + ccName: fabricContractName, + targetOrganizations: [org1Env, org2Env], + caFile: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + ccLabel: "basic-asset-transfer-2", + ccLang: ChainCodeProgrammingLanguage.Typescript, + ccSequence: 1, + orderer: "orderer.example.com:7050", + ordererTLSHostnameOverride: "orderer.example.com", + connTimeout: 60, + }); + + const { packageIds, lifecycle, success } = res.data; + expect(res.status).toBe(200); + expect(success).toBe(true); + expect(lifecycle).not.toBeUndefined(); + + const { + approveForMyOrgList, + installList, + queryInstalledList, + commit, + packaging, + queryCommitted, + } = lifecycle; + + expect(packageIds).toBeTruthy(); + expect(packageIds).toBeArray(); + + expect(approveForMyOrgList).toBeTruthy(); + expect(approveForMyOrgList).toBeArray(); + + expect(installList).toBeTruthy(); + expect(installList).toBeArray(); + expect(queryInstalledList).toBeTruthy(); + expect(queryInstalledList).toBeArray(); + + expect(commit).toBeTruthy(); + expect(packaging).toBeTruthy(); + expect(queryCommitted).toBeTruthy(); + log.info("Fabric Contract deployed"); + + fabricSigningCredential = { + keychainId, + keychainRef: keychainEntryKey, + }; + + const createResponse = await fabricApi.runTransactionV1({ + contractName: fabricContractName, + channelName: fabricChannelName, + params: [FABRIC_ASSET_ID, "19"], + methodName: "CreateAsset", + invocationType: FabricContractInvocationType.Send, + signingCredential: fabricSigningCredential, + }); + + expect(createResponse).not.toBeUndefined(); + expect(createResponse.status).toBeGreaterThan(199); + expect(createResponse.status).toBeLessThan(300); + + log.info( + `BassicAssetTransfer.Create(): ${JSON.stringify(createResponse.data)}`, + ); + return "Fabric Network setup successful"; +} +async function setupBesuTestLedger(): Promise { + besuLedger = new BesuTestLedger({ + logLevel, + emitContainerLogs: true, + envVars: ["BESU_NETWORK=dev"], + }); + await besuLedger.start(); + log.info("Besu test ledger initialized"); + rpcApiHttpHost = await besuLedger.getRpcApiHttpHost(); + rpcApiWsHost = await besuLedger.getRpcApiWsHost(); + web3 = new Web3(rpcApiHttpHost); + firstHighNetWorthAccount = besuLedger.getGenesisAccountPubKey(); + + testEthAccount = await besuLedger.createEthTestAccount(); + + besuKeyPair = { + privateKey: besuLedger.getGenesisAccountPrivKey(), + }; + + besuContractName = "LockAsset"; + + const keychainEntryValue = besuKeyPair.privateKey; + const keychainEntryKey = uuidv4(); + besuKeychainPlugin = new PluginKeychainMemory({ + instanceId: uuidv4(), + keychainId: uuidv4(), + + backend: new Map([[keychainEntryKey, keychainEntryValue]]), + logLevel, + }); + + besuKeychainPlugin.set( + LockAssetContractJson.contractName, + JSON.stringify(LockAssetContractJson), + ); + + const pluginRegistry = new PluginRegistry({ + plugins: [besuKeychainPlugin], + }); + + const options: IPluginLedgerConnectorBesuOptions = { + instanceId: uuidv4(), + rpcApiHttpHost, + rpcApiWsHost, + pluginRegistry, + logLevel, + }; + + besuConnector = new PluginLedgerConnectorBesu(options); + pluginRegistry.add(besuConnector); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + besuServer = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 4000, + server: besuServer, + }; + + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + const { address, port } = addressInfo; + + await besuConnector.getOrCreateWebServices(); + const wsApi = new SocketIoServer(besuServer, { + path: Constants.SocketIoConnectionPathV1, + }); + await besuConnector.registerWebServices(expressApp, wsApi); + besuPath = `http://${address}:${port}`; + log.info("Besu connector initialized"); + + await besuConnector.transact({ + web3SigningCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + consistencyStrategy: { + blockConfirmations: 0, + receiptType: ReceiptType.NodeTxPoolAck, + }, + transactionConfig: { + from: firstHighNetWorthAccount, + to: testEthAccount.address, + value: 10e9, + gas: 1000000, + }, + }); + const balance = await web3.eth.getBalance(testEthAccount.address); + expect(balance).toBeTruthy(); + expect(parseInt(balance, 10)).toBeGreaterThan(10e9); + + const deployOut = await besuConnector.deployContract({ + keychainId: besuKeychainPlugin.getKeychainId(), + contractName: LockAssetContractJson.contractName, + contractAbi: LockAssetContractJson.abi, + constructorArgs: [], + web3SigningCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + bytecode: LockAssetContractJson.bytecode, + gas: 1000000, + }); + expect(deployOut).toBeTruthy(); + expect(deployOut.transactionReceipt).toBeTruthy(); + expect(deployOut.transactionReceipt.contractAddress).toBeTruthy(); + log.info("Besu contract Deployed successfully"); + + const res = await besuConnector.invokeContract({ + contractName: besuContractName, + keychainId: besuKeychainPlugin.getKeychainId(), + invocationType: EthContractInvocationType.Send, + methodName: "createAsset", + params: [BESU_ASSET_ID, 19], + signingCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + gas: 1000000, + }); + expect(res).toBeTruthy(); + expect(res.success).toBeTruthy(); + + log.info("Besu asset created successfully"); + + besuSigningCredential = { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }; + besuContractAddress = deployOut.transactionReceipt.contractAddress as string; + return "Besu Network setup successful"; +} diff --git a/packages/cactus-plugin-bungee/src/test/typescript/integration/fabric-test-basic.test.ts b/packages/cactus-plugin-bungee/src/test/typescript/integration/fabric-test-basic.test.ts new file mode 100644 index 00000000000..790a568918c --- /dev/null +++ b/packages/cactus-plugin-bungee/src/test/typescript/integration/fabric-test-basic.test.ts @@ -0,0 +1,484 @@ +import { + IListenOptions, + LogLevelDesc, + LoggerProvider, + Secp256k1Keys, + Servers, +} from "@hyperledger/cactus-common"; +import "jest-extended"; + +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; +import { DiscoveryOptions } from "fabric-network"; +import bodyParser from "body-parser"; +import path from "path"; + +import http, { Server } from "http"; + +import fs from "fs-extra"; + +import { + Configuration, + DefaultEventHandlerStrategy, + FabricSigningCredential, + IPluginLedgerConnectorFabricOptions, + PluginLedgerConnectorFabric, + DefaultApi as FabricApi, + FileBase64, + ChainCodeProgrammingLanguage, + FabricContractInvocationType, +} from "@hyperledger/cactus-plugin-ledger-connector-fabric"; +import { + Containers, + DEFAULT_FABRIC_2_AIO_FABRIC_VERSION, + DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + DEFAULT_FABRIC_2_AIO_IMAGE_VERSION, + FabricTestLedgerV1, + pruneDockerAllIfGithubAction, +} from "@hyperledger/cactus-test-tooling"; +import express from "express"; +import { AddressInfo } from "net"; + +import { v4 as uuidv4 } from "uuid"; +import { + PluginBUNGEE, + IPluginBUNGEEOptions, +} from "../../../main/typescript/plugin-bungee"; +import { + FabricNetworkDetails, + StrategyFabric, +} from "../../../main/typescript/strategy/strategy-fabric"; + +let fabricServer: Server; + +let fabricSigningCredential: FabricSigningCredential; +const logLevel: LogLevelDesc = "INFO"; + +let fabricLedger: FabricTestLedgerV1; +let fabricContractName: string; +let fabricChannelName: string; +let fabricPath: string; + +let configFabric: Configuration; +let apiClient: FabricApi; + +let fabricConnector: PluginLedgerConnectorFabric; +let pluginBungeeFabricOptions: IPluginBUNGEEOptions; +let pluginBungee: PluginBUNGEE; +const FABRIC_ASSET_ID = uuidv4(); + +let networkDetails: FabricNetworkDetails; + +const log = LoggerProvider.getOrCreate({ + level: logLevel, + label: "BUNGEE dummy testing", +}); + +beforeAll(async () => { + pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + log.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); + + { + // Fabric ledger connection + const channelId = "mychannel"; + fabricChannelName = channelId; + + fabricLedger = new FabricTestLedgerV1({ + emitContainerLogs: true, + publishAllPorts: true, + imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + imageVersion: DEFAULT_FABRIC_2_AIO_IMAGE_VERSION, + envVars: new Map([ + ["FABRIC_VERSION", DEFAULT_FABRIC_2_AIO_FABRIC_VERSION], + ]), + logLevel, + }); + + await fabricLedger.start(); + log.info("Fabric Ledger started"); + + const connectionProfile = await fabricLedger.getConnectionProfileOrg1(); + expect(connectionProfile).not.toBeUndefined(); + + const enrollAdminOut = await fabricLedger.enrollAdmin(); + const adminWallet = enrollAdminOut[1]; + const [userIdentity] = await fabricLedger.enrollUser(adminWallet); + const sshConfig = await fabricLedger.getSshConfig(); + + log.info("enrolled admin"); + + const keychainInstanceId = uuidv4(); + const keychainId = uuidv4(); + const keychainEntryKey = "user1"; + const keychainEntryValue = JSON.stringify(userIdentity); + + const keychainPlugin = new PluginKeychainMemory({ + instanceId: keychainInstanceId, + keychainId, + logLevel, + backend: new Map([ + [keychainEntryKey, keychainEntryValue], + ["some-other-entry-key", "some-other-entry-value"], + ]), + }); + + const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); + + const discoveryOptions: DiscoveryOptions = { + enabled: true, + asLocalhost: true, + }; + + // This is the directory structure of the Fabirc 2.x CLI container (fabric-tools image) + // const orgCfgDir = "/fabric-samples/test-network/organizations/"; + const orgCfgDir = + "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/"; + + // these below mirror how the fabric-samples sets up the configuration + const org1Env = { + CORE_LOGGING_LEVEL: "debug", + FABRIC_LOGGING_SPEC: "debug", + CORE_PEER_LOCALMSPID: "Org1MSP", + + ORDERER_CA: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + + FABRIC_CFG_PATH: "/etc/hyperledger/fabric", + CORE_PEER_TLS_ENABLED: "true", + CORE_PEER_TLS_ROOTCERT_FILE: `${orgCfgDir}peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt`, + CORE_PEER_MSPCONFIGPATH: `${orgCfgDir}peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp`, + CORE_PEER_ADDRESS: "peer0.org1.example.com:7051", + ORDERER_TLS_ROOTCERT_FILE: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + }; + + // these below mirror how the fabric-samples sets up the configuration + const org2Env = { + CORE_LOGGING_LEVEL: "debug", + FABRIC_LOGGING_SPEC: "debug", + CORE_PEER_LOCALMSPID: "Org2MSP", + + FABRIC_CFG_PATH: "/etc/hyperledger/fabric", + CORE_PEER_TLS_ENABLED: "true", + ORDERER_CA: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + + CORE_PEER_ADDRESS: "peer0.org2.example.com:9051", + CORE_PEER_MSPCONFIGPATH: `${orgCfgDir}peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp`, + CORE_PEER_TLS_ROOTCERT_FILE: `${orgCfgDir}peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt`, + ORDERER_TLS_ROOTCERT_FILE: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + }; + + const pluginOptions: IPluginLedgerConnectorFabricOptions = { + instanceId: uuidv4(), + dockerBinary: "/usr/local/bin/docker", + peerBinary: "/fabric-samples/bin/peer", + goBinary: "/usr/local/go/bin/go", + pluginRegistry, + cliContainerEnv: org1Env, + sshConfig, + logLevel: "INFO", + connectionProfile, + discoveryOptions, + eventHandlerOptions: { + strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, + commitTimeout: 300, + }, + }; + + fabricConnector = new PluginLedgerConnectorFabric(pluginOptions); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + fabricServer = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 3000, + server: fabricServer, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + const { address, port } = addressInfo; + + await fabricConnector.getOrCreateWebServices(); + await fabricConnector.registerWebServices(expressApp); + + log.info("Fabric Ledger connector check"); + + const apiUrl = `http://${address}:${port}`; + + fabricPath = apiUrl; + configFabric = new Configuration({ basePath: apiUrl }); + + apiClient = new FabricApi(configFabric); + + // deploy contracts ... + fabricContractName = "basic-asset-transfer-2"; + const contractRelPath = + "../fabric-contracts/simple-asset/chaincode-typescript"; + const contractDir = path.join(__dirname, contractRelPath); + + // ├── package.json + // ├── src + // │ ├── assetTransfer.ts + // │ ├── asset.ts + // │ └── index.ts + // ├── tsconfig.json + // -------- + const sourceFiles: FileBase64[] = []; + { + const filename = "./tsconfig.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./package.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./index.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./asset.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./assetTransfer.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + + const res = await apiClient.deployContractV1({ + channelId, + ccVersion: "1.0.0", + sourceFiles, + ccName: fabricContractName, + targetOrganizations: [org1Env, org2Env], + caFile: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + ccLabel: "basic-asset-transfer-2", + ccLang: ChainCodeProgrammingLanguage.Typescript, + ccSequence: 1, + orderer: "orderer.example.com:7050", + ordererTLSHostnameOverride: "orderer.example.com", + connTimeout: 60, + }); + + const { packageIds, lifecycle, success } = res.data; + expect(res.status).toBe(200); + expect(success).toBe(true); + expect(lifecycle).not.toBeUndefined(); + + const { + approveForMyOrgList, + installList, + queryInstalledList, + commit, + packaging, + queryCommitted, + } = lifecycle; + + expect(packageIds).toBeTruthy(); + expect(packageIds).toBeArray(); + + expect(approveForMyOrgList).toBeTruthy(); + expect(approveForMyOrgList).toBeArray(); + + expect(installList).toBeTruthy(); + expect(installList).toBeArray(); + expect(queryInstalledList).toBeTruthy(); + expect(queryInstalledList).toBeArray(); + + expect(commit).toBeTruthy(); + expect(packaging).toBeTruthy(); + expect(queryCommitted).toBeTruthy(); + log.info("Contract deployed"); + + fabricSigningCredential = { + keychainId, + keychainRef: keychainEntryKey, + }; + const createResponse = await apiClient.runTransactionV1({ + contractName: fabricContractName, + channelName: fabricChannelName, + params: [FABRIC_ASSET_ID, "19"], + methodName: "CreateAsset", + invocationType: FabricContractInvocationType.Send, + signingCredential: fabricSigningCredential, + }); + + expect(createResponse).not.toBeUndefined(); + expect(createResponse.status).toBeGreaterThan(199); + expect(createResponse.status).toBeLessThan(300); + + log.info( + `BassicAssetTransfer.Create(): ${JSON.stringify(createResponse.data)}`, + ); + + pluginBungeeFabricOptions = { + keyPair: Secp256k1Keys.generateKeyPairsBuffer(), + instanceId: uuidv4(), + }; + + networkDetails = { + connectorApiPath: fabricPath, + signingCredential: fabricSigningCredential, + channelName: fabricChannelName, + contractName: fabricContractName, + participant: "Org1MSP", + }; + + pluginBungee = new PluginBUNGEE(pluginBungeeFabricOptions); + } +}); + +test("test creation of views for different timeframes and states", async () => { + const strategy = "FABRIC"; + pluginBungee.addStrategy(strategy, new StrategyFabric("INFO")); + + const snapshot = await pluginBungee.generateSnapshot( + [], + strategy, + networkDetails, + ); + const view = pluginBungee.generateView( + snapshot, + "0", + "9999999999999", + undefined, + ); + + //expect to return a view + expect(view.view).toBeTruthy(); + expect(view.signature).toBeTruthy(); + + //expect the view to have capture the new asset Fabric_ASSET_ID, and attributes to match + expect(snapshot.getStateBins().length).toEqual(1); + expect(snapshot.getStateBins()[0].getId()).toEqual(FABRIC_ASSET_ID); + expect(snapshot.getStateBins()[0].getTransactions().length).toEqual(1); + + //fabric transaction proofs include endorsements + expect( + snapshot.getStateBins()[0].getTransactions()[0].getProof().getEndorsements() + ?.length, + ).toEqual(2); + + //no valid states for this time frame + const view1 = pluginBungee.generateView(snapshot, "0", "9999", undefined); + expect(view1.view).toBeUndefined(); + expect(view1.signature).toBeUndefined(); + + //creating new asset + const new_asset_id = uuidv4(); + const createResponse = await apiClient.runTransactionV1({ + contractName: fabricContractName, + channelName: fabricChannelName, + params: [new_asset_id, "10"], + methodName: "CreateAsset", + invocationType: FabricContractInvocationType.Send, + signingCredential: fabricSigningCredential, + }); + expect(createResponse).not.toBeUndefined(); + expect(createResponse.status).toBeGreaterThan(199); + expect(createResponse.status).toBeLessThan(300); + + //changing FABRIC_ASSET_ID value + const modifyResponse = await apiClient.runTransactionV1({ + contractName: fabricContractName, + channelName: fabricChannelName, + params: [FABRIC_ASSET_ID, "18"], + methodName: "UpdateAsset", + invocationType: FabricContractInvocationType.Send, + signingCredential: fabricSigningCredential, + }); + expect(modifyResponse).not.toBeUndefined(); + expect(modifyResponse.status).toBeGreaterThan(199); + expect(modifyResponse.status).toBeLessThan(300); + + const snapshot1 = await pluginBungee.generateSnapshot( + [], + strategy, + networkDetails, + ); + const view2 = pluginBungee.generateView( + snapshot1, + "0", + "999999999999", + undefined, + ); + + //expect to return a view + expect(view2.view).toBeTruthy(); + expect(view2.signature).toBeTruthy(); + + //expect to have captured state for both assets + const stateBins = snapshot1.getStateBins(); + expect(stateBins.length).toEqual(2); + const bins = [stateBins[0].getId(), stateBins[1].getId()]; + + expect(bins.includes(FABRIC_ASSET_ID)).toBeTrue(); + expect(bins.includes(new_asset_id)).toBeTrue(); + + //checks if values match: + // - new value of FABRIC_ASSET_ID state in new snapshot equals to new value) + // - successfully captured transaction that created the new asset + if (bins[0] === FABRIC_ASSET_ID) { + expect(snapshot1.getStateBins()[0].getTransactions().length).toEqual(2); + expect(snapshot1.getStateBins()[0].getValue()).toEqual("18"); + expect(snapshot1.getStateBins()[1].getTransactions().length).toEqual(1); + } else { + expect(snapshot1.getStateBins()[0].getTransactions().length).toEqual(1); + expect(snapshot1.getStateBins()[1].getTransactions().length).toEqual(2); + expect(snapshot1.getStateBins()[1].getValue()).toEqual("18"); + } +}); + +afterAll(async () => { + await fabricLedger.stop(); + await fabricLedger.destroy(); + await Servers.shutdown(fabricServer); + + await pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + log.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); +}); diff --git a/packages/cactus-plugin-bungee/src/test/typescript/integration/fabric-test-pruning.test.ts b/packages/cactus-plugin-bungee/src/test/typescript/integration/fabric-test-pruning.test.ts new file mode 100644 index 00000000000..93d0ac3b6bc --- /dev/null +++ b/packages/cactus-plugin-bungee/src/test/typescript/integration/fabric-test-pruning.test.ts @@ -0,0 +1,468 @@ +import { + IListenOptions, + LogLevelDesc, + LoggerProvider, + Secp256k1Keys, + Servers, +} from "@hyperledger/cactus-common"; +import "jest-extended"; + +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; +import { DiscoveryOptions } from "fabric-network"; +import bodyParser from "body-parser"; +import path from "path"; + +import http, { Server } from "http"; + +import fs from "fs-extra"; + +import { + Configuration, + DefaultEventHandlerStrategy, + FabricSigningCredential, + IPluginLedgerConnectorFabricOptions, + PluginLedgerConnectorFabric, + DefaultApi as FabricApi, + FileBase64, + ChainCodeProgrammingLanguage, + FabricContractInvocationType, +} from "@hyperledger/cactus-plugin-ledger-connector-fabric"; +import { + Containers, + DEFAULT_FABRIC_2_AIO_FABRIC_VERSION, + DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + DEFAULT_FABRIC_2_AIO_IMAGE_VERSION, + FabricTestLedgerV1, + pruneDockerAllIfGithubAction, +} from "@hyperledger/cactus-test-tooling"; +import express from "express"; +import { AddressInfo } from "net"; + +import { v4 as uuidv4 } from "uuid"; +import { + FabricNetworkDetails, + StrategyFabric, +} from "../../../main/typescript/strategy/strategy-fabric"; +import { + IPluginBUNGEEOptions, + PluginBUNGEE, +} from "../../../main/typescript/plugin-bungee"; + +let fabricServer: Server; + +let fabricSigningCredential: FabricSigningCredential; +const logLevel: LogLevelDesc = "INFO"; + +let fabricLedger: FabricTestLedgerV1; +let fabricContractName: string; +let fabricChannelName: string; +let fabricPath: string; + +let configFabric: Configuration; +let apiClient: FabricApi; + +let fabricConnector: PluginLedgerConnectorFabric; +let pluginBungeeFabricOptions: IPluginBUNGEEOptions; +let pluginBungee: PluginBUNGEE; +const FABRIC_ASSET_ID = uuidv4(); + +let networkDetails: FabricNetworkDetails; + +const log = LoggerProvider.getOrCreate({ + level: logLevel, + label: "BUNGEE dummy testing", +}); + +beforeAll(async () => { + pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + log.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); + + { + // Fabric ledger connection + const channelId = "mychannel"; + fabricChannelName = channelId; + + fabricLedger = new FabricTestLedgerV1({ + emitContainerLogs: true, + publishAllPorts: true, + imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + imageVersion: DEFAULT_FABRIC_2_AIO_IMAGE_VERSION, + envVars: new Map([ + ["FABRIC_VERSION", DEFAULT_FABRIC_2_AIO_FABRIC_VERSION], + ]), + logLevel, + }); + + await fabricLedger.start(); + log.info("Fabric Ledger started"); + + const connectionProfile = await fabricLedger.getConnectionProfileOrg1(); + expect(connectionProfile).not.toBeUndefined(); + + const enrollAdminOut = await fabricLedger.enrollAdmin(); + const adminWallet = enrollAdminOut[1]; + const [userIdentity] = await fabricLedger.enrollUser(adminWallet); + const sshConfig = await fabricLedger.getSshConfig(); + + log.info("enrolled admin"); + + const keychainInstanceId = uuidv4(); + const keychainId = uuidv4(); + const keychainEntryKey = "user1"; + const keychainEntryValue = JSON.stringify(userIdentity); + + const keychainPlugin = new PluginKeychainMemory({ + instanceId: keychainInstanceId, + keychainId, + logLevel, + backend: new Map([ + [keychainEntryKey, keychainEntryValue], + ["some-other-entry-key", "some-other-entry-value"], + ]), + }); + + const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); + + const discoveryOptions: DiscoveryOptions = { + enabled: true, + asLocalhost: true, + }; + + // This is the directory structure of the Fabirc 2.x CLI container (fabric-tools image) + // const orgCfgDir = "/fabric-samples/test-network/organizations/"; + const orgCfgDir = + "/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/"; + + // these below mirror how the fabric-samples sets up the configuration + const org1Env = { + CORE_LOGGING_LEVEL: "debug", + FABRIC_LOGGING_SPEC: "debug", + CORE_PEER_LOCALMSPID: "Org1MSP", + + ORDERER_CA: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + + FABRIC_CFG_PATH: "/etc/hyperledger/fabric", + CORE_PEER_TLS_ENABLED: "true", + CORE_PEER_TLS_ROOTCERT_FILE: `${orgCfgDir}peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt`, + CORE_PEER_MSPCONFIGPATH: `${orgCfgDir}peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp`, + CORE_PEER_ADDRESS: "peer0.org1.example.com:7051", + ORDERER_TLS_ROOTCERT_FILE: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + }; + + // these below mirror how the fabric-samples sets up the configuration + const org2Env = { + CORE_LOGGING_LEVEL: "debug", + FABRIC_LOGGING_SPEC: "debug", + CORE_PEER_LOCALMSPID: "Org2MSP", + + FABRIC_CFG_PATH: "/etc/hyperledger/fabric", + CORE_PEER_TLS_ENABLED: "true", + ORDERER_CA: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + + CORE_PEER_ADDRESS: "peer0.org2.example.com:9051", + CORE_PEER_MSPCONFIGPATH: `${orgCfgDir}peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp`, + CORE_PEER_TLS_ROOTCERT_FILE: `${orgCfgDir}peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt`, + ORDERER_TLS_ROOTCERT_FILE: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + }; + + const pluginOptions: IPluginLedgerConnectorFabricOptions = { + instanceId: uuidv4(), + dockerBinary: "/usr/local/bin/docker", + peerBinary: "/fabric-samples/bin/peer", + goBinary: "/usr/local/go/bin/go", + pluginRegistry, + cliContainerEnv: org1Env, + sshConfig, + logLevel: "INFO", + connectionProfile, + discoveryOptions, + eventHandlerOptions: { + strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, + commitTimeout: 300, + }, + }; + + fabricConnector = new PluginLedgerConnectorFabric(pluginOptions); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + fabricServer = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 3000, + server: fabricServer, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + const { address, port } = addressInfo; + + await fabricConnector.getOrCreateWebServices(); + await fabricConnector.registerWebServices(expressApp); + + log.info("Fabric Ledger connector check"); + + const apiUrl = `http://${address}:${port}`; + /*fabricPath = apiUrl; + const config = new Configuration({ basePath: apiUrl }); + + const apiClient = new FabricApi(config); + */ + + fabricPath = apiUrl; + configFabric = new Configuration({ basePath: apiUrl }); + + apiClient = new FabricApi(configFabric); + + // deploy contracts ... + fabricContractName = "basic-asset-transfer-2"; + const contractRelPath = + "../fabric-contracts/simple-asset/chaincode-typescript"; + const contractDir = path.join(__dirname, contractRelPath); + + // ├── package.json + // ├── src + // │ ├── assetTransfer.ts + // │ ├── asset.ts + // │ └── index.ts + // ├── tsconfig.json + // -------- + const sourceFiles: FileBase64[] = []; + { + const filename = "./tsconfig.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./package.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./index.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./asset.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./assetTransfer.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + + const res = await apiClient.deployContractV1({ + channelId, + ccVersion: "1.0.0", + sourceFiles, + ccName: fabricContractName, + targetOrganizations: [org1Env, org2Env], + caFile: `${orgCfgDir}ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem`, + ccLabel: "basic-asset-transfer-2", + ccLang: ChainCodeProgrammingLanguage.Typescript, + ccSequence: 1, + orderer: "orderer.example.com:7050", + ordererTLSHostnameOverride: "orderer.example.com", + connTimeout: 60, + }); + + const { packageIds, lifecycle, success } = res.data; + expect(res.status).toBe(200); + expect(success).toBe(true); + expect(lifecycle).not.toBeUndefined(); + + const { + approveForMyOrgList, + installList, + queryInstalledList, + commit, + packaging, + queryCommitted, + } = lifecycle; + + expect(packageIds).toBeTruthy(); + expect(packageIds).toBeArray(); + + expect(approveForMyOrgList).toBeTruthy(); + expect(approveForMyOrgList).toBeArray(); + + expect(installList).toBeTruthy(); + expect(installList).toBeArray(); + expect(queryInstalledList).toBeTruthy(); + expect(queryInstalledList).toBeArray(); + + expect(commit).toBeTruthy(); + expect(packaging).toBeTruthy(); + expect(queryCommitted).toBeTruthy(); + log.info("Contract deployed"); + + fabricSigningCredential = { + keychainId, + keychainRef: keychainEntryKey, + }; + const createResponse = await apiClient.runTransactionV1({ + contractName: fabricContractName, + channelName: fabricChannelName, + params: [FABRIC_ASSET_ID, "19"], + methodName: "CreateAsset", + invocationType: FabricContractInvocationType.Send, + signingCredential: fabricSigningCredential, + }); + + expect(createResponse).not.toBeUndefined(); + expect(createResponse.status).toBeGreaterThan(199); + expect(createResponse.status).toBeLessThan(300); + + log.info( + `BassicAssetTransfer.Create(): ${JSON.stringify(createResponse.data)}`, + ); + + pluginBungeeFabricOptions = { + keyPair: Secp256k1Keys.generateKeyPairsBuffer(), + instanceId: uuidv4(), + }; + + networkDetails = { + connectorApiPath: fabricPath, + signingCredential: fabricSigningCredential, + channelName: fabricChannelName, + contractName: fabricContractName, + participant: "Org1MSP", + }; + + pluginBungee = new PluginBUNGEE(pluginBungeeFabricOptions); + } +}); + +test("test creation of views for specific timeframes", async () => { + const strategy = "FABRIC"; + pluginBungee.addStrategy(strategy, new StrategyFabric("INFO")); + + const snapshot = await pluginBungee.generateSnapshot( + [], + strategy, + networkDetails, + ); + const view = pluginBungee.generateView( + snapshot, + "0", + "9999999999999", + undefined, + ); + //expect to return a view + expect(view.view).toBeTruthy(); + expect(view.signature).toBeTruthy(); + + //expect the view to have capture the new asset FABRIC_ASSET_ID, and attributes to match + expect(snapshot.getStateBins().length).toEqual(1); + expect(snapshot.getStateBins()[0].getId()).toEqual(FABRIC_ASSET_ID); + expect(snapshot.getStateBins()[0].getTransactions().length).toEqual(1); + //fabric transaction proofs include endorsements + expect( + snapshot.getStateBins()[0].getTransactions()[0].getProof().getEndorsements() + ?.length, + ).toEqual(2); + + //changing FABRIC_ASSET_ID value + const modifyResponse = await apiClient.runTransactionV1({ + contractName: fabricContractName, + channelName: fabricChannelName, + params: [FABRIC_ASSET_ID, "18"], + methodName: "UpdateAsset", + invocationType: FabricContractInvocationType.Send, + signingCredential: fabricSigningCredential, + }); + expect(modifyResponse).not.toBeUndefined(); + expect(modifyResponse.status).toBeGreaterThan(199); + expect(modifyResponse.status).toBeLessThan(300); + + const snapshot1 = await pluginBungee.generateSnapshot( + [], + strategy, + networkDetails, + ); + + //tI is the time of the first transaction +1 + const tI = ( + parseInt(snapshot.getStateBins()[0].getTransactions()[0].getTimeStamp()) + 1 + ).toString(); + + expect(snapshot1.getStateBins().length).toEqual(1); + expect(snapshot1.getStateBins()[0].getId()).toEqual(FABRIC_ASSET_ID); + expect(snapshot1.getStateBins()[0].getTransactions().length).toEqual(2); + expect(snapshot1.getStateBins()[0].getValue()).not.toEqual( + snapshot.getStateBins()[0].getValue(), + ); + const view1 = pluginBungee.generateView( + snapshot1, + tI, + "9999999999999", + undefined, + ); + + //expect to return a view + expect(view1.view).toBeTruthy(); + expect(view1.signature).toBeTruthy(); + + expect(snapshot1.getStateBins().length).toEqual(1); + expect(snapshot1.getStateBins()[0].getId()).toEqual(FABRIC_ASSET_ID); + //expect the view to not include first transaction (made before tI) + expect(snapshot1.getStateBins()[0].getTransactions().length).toEqual(1); + //expect old and new snapshot state values to differ + expect(snapshot1.getStateBins()[0].getValue()).not.toEqual( + snapshot.getStateBins()[0].getValue(), + ); +}); + +afterAll(async () => { + await fabricLedger.stop(); + await fabricLedger.destroy(); + await Servers.shutdown(fabricServer); + + await pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + log.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); +}); diff --git a/packages/cactus-plugin-bungee/src/test/typescript/solidity/lock-asset-contract/LockAsset.json b/packages/cactus-plugin-bungee/src/test/typescript/solidity/lock-asset-contract/LockAsset.json new file mode 100644 index 00000000000..df101a2ba34 --- /dev/null +++ b/packages/cactus-plugin-bungee/src/test/typescript/solidity/lock-asset-contract/LockAsset.json @@ -0,0 +1,3865 @@ +{ + "contractName": "LockAsset", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "id", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isLock", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "size", + "type": "uint256" + } + ], + "name": "Transaction", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "id", + "type": "string" + }, + { + "internalType": "uint256", + "name": "size", + "type": "uint256" + } + ], + "name": "createAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "id", + "type": "string" + } + ], + "name": "deleteAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllAssetsIDs", + "outputs": [ + { + "internalType": "string[]", + "name": "", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "id", + "type": "string" + } + ], + "name": "getAsset", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "bool", + "name": "isLock", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "size", + "type": "uint256" + } + ], + "internalType": "struct Asset", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "id", + "type": "string" + } + ], + "name": "isAssetLocked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "id", + "type": "string" + } + ], + "name": "isPresent", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "id", + "type": "string" + } + ], + "name": "lockAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "id", + "type": "string" + } + ], + "name": "unLockAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"id\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isLock\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"size\",\"type\":\"uint256\"}],\"name\":\"Transaction\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"id\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"size\",\"type\":\"uint256\"}],\"name\":\"createAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"id\",\"type\":\"string\"}],\"name\":\"deleteAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAssetsIDs\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"\",\"type\":\"string[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"id\",\"type\":\"string\"}],\"name\":\"getAsset\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isLock\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"size\",\"type\":\"uint256\"}],\"internalType\":\"struct Asset\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"id\",\"type\":\"string\"}],\"name\":\"isAssetLocked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"id\",\"type\":\"string\"}],\"name\":\"isPresent\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"id\",\"type\":\"string\"}],\"name\":\"lockAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"id\",\"type\":\"string\"}],\"name\":\"unLockAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"/workspaces/blockchain-integration-framework/packages/cactus-plugin-bungee/src/test/typescript/solidity/lock-asset-contract/lock-asset.sol\":\"LockAsset\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"/workspaces/blockchain-integration-framework/packages/cactus-plugin-bungee/src/test/typescript/solidity/lock-asset-contract/lock-asset.sol\":{\"keccak256\":\"0x8666cf45ca92a56370f20b5391bb801cd826f57cbfde5e717dadade9d5ed5582\",\"urls\":[\"bzz-raw://91cc30b4b79e7d9219ee39dc6d24abadc78d66d0dd650af3818cb406cf60b083\",\"dweb:/ipfs/QmV7pQLQ6WPGgEwFa1dAzn4ZxDm8ZwyikiG9aB2Dn7bbCe\"]}},\"version\":1}", + "bytecode": "608060405234801561001057600080fd5b50610b16806100206000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063cd5286d01161005b578063cd5286d0146100f2578063db9cc41014610132578063def60e0d14610145578063e24aa37c1461015857600080fd5b80631ae4eb681461008d5780635137b8a7146100b55780635e82d0a6146100ca578063bc548275146100df575b600080fd5b6100a061009b366004610850565b61016b565b60405190151581526020015b60405180910390f35b6100bd6101d5565b6040516100ac9190610892565b6100dd6100d8366004610850565b6102ae565b005b6100a06100ed366004610850565b610404565b610105610100366004610850565b610433565b6040805182516001600160a01b0316815260208084015115159082015291810151908201526060016100ac565b6100dd610140366004610924565b6104ab565b6100dd610153366004610850565b610606565b6100dd610166366004610850565b61064c565b60008060018484604051610180929190610970565b9081526040519081900360200190205460ff1690508061019f57600080fd5b600084846040516101b1929190610970565b9081526040519081900360200190205460ff600160a01b9091041691505092915050565b60606002805480602002602001604051908101604052809291908181526020016000905b828210156102a557838290600052602060002001805461021890610980565b80601f016020809104026020016040519081016040528092919081815260200182805461024490610980565b80156102915780601f1061026657610100808354040283529160200191610291565b820191906000526020600020905b81548152906001019060200180831161027457829003601f168201915b5050505050815260200190600101906101f9565b50505050905090565b6000600183836040516102c2929190610970565b9081526040519081900360200190205460ff169050806102e157600080fd5b6001600084846040516102f5929190610970565b9081526040519081900360200181208054921515600160a01b0260ff60a01b199093169290921790915561032c9084908490610970565b60405180910390207f9db172bd887aec98e834d86fb9ff0f1549ae602b8ca8ba1ee50902e4d502b9a060008585604051610367929190610970565b908152604051908190036020018120546001600160a01b0316906000906103919088908890610970565b9081526040519081900360200181205460ff600160a01b90910416906000906103bd9089908990610970565b908152604051908190036020018120600101546103f79392916001600160a01b039390931683529015156020830152604082015260600190565b60405180910390a2505050565b600060018383604051610418929190610970565b9081526040519081900360200190205460ff16905092915050565b604080516060810182526000808252602082018190529181019190915260008383604051610462929190610970565b908152604080516020928190038301812060608201835280546001600160a01b0381168352600160a01b900460ff16151593820193909352600190920154908201529392505050565b600081116104b857600080fd5b80600084846040516104cb929190610970565b90815260200160405180910390206001018190555033600084846040516104f3929190610970565b90815260405190819003602001812080546001600160a01b03939093166001600160a01b03199093169290921790915560009081906105359086908690610970565b9081526040519081900360200181208054921515600160a01b0260ff60a01b199093169290921790915560019061056f9085908590610970565b9081526040519081900360200190205460ff166105c557600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace016105c3838583610a1f565b505b60018084846040516105d8929190610970565b908152604051908190036020018120805492151560ff199093169290921790915561032c9084908490610970565b60006001838360405161061a929190610970565b9081526040519081900360200190205460ff1690508061063957600080fd5b60008084846040516102f5929190610970565b600060018383604051610660929190610970565b9081526040519081900360200190205460ff1690508061067f57600080fd5b6000808484604051610692929190610970565b9081526040519081900360200190205460ff600160a01b909104169050806106b957600080fd5b600084846040516106cb929190610970565b90815260405190819003602001812080546001600160a81b031916815560006001918201819055916107009087908790610970565b908152604051908190036020018120805492151560ff199093169290921790915561072e9085908590610970565b60405180910390207f9db172bd887aec98e834d86fb9ff0f1549ae602b8ca8ba1ee50902e4d502b9a060008686604051610769929190610970565b908152604051908190036020018120546001600160a01b0316906000906107939089908990610970565b9081526040519081900360200181205460ff600160a01b90910416906000906107bf908a908a90610970565b908152604051908190036020018120600101546107f99392916001600160a01b039390931683529015156020830152604082015260600190565b60405180910390a250505050565b60008083601f84011261081957600080fd5b50813567ffffffffffffffff81111561083157600080fd5b60208301915083602082850101111561084957600080fd5b9250929050565b6000806020838503121561086357600080fd5b823567ffffffffffffffff81111561087a57600080fd5b61088685828601610807565b90969095509350505050565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b8381101561091657888603603f1901855282518051808852835b818110156108ef578281018a01518982018b015289016108d4565b508781018901849052601f01601f19169096018701955093860193918601916001016108ba565b509398975050505050505050565b60008060006040848603121561093957600080fd5b833567ffffffffffffffff81111561095057600080fd5b61095c86828701610807565b909790965060209590950135949350505050565b8183823760009101908152919050565b600181811c9082168061099457607f821691505b6020821081036109b457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b601f821115610a1a57600081815260208120601f850160051c810160208610156109f75750805b601f850160051c820191505b81811015610a1657828155600101610a03565b5050505b505050565b67ffffffffffffffff831115610a3757610a376109ba565b610a4b83610a458354610980565b836109d0565b6000601f841160018114610a7f5760008515610a675750838201355b600019600387901b1c1916600186901b178355610ad9565b600083815260209020601f19861690835b82811015610ab05786850135825560209485019460019092019101610a90565b5086821015610acd5760001960f88860031b161c19848701351681555b505060018560011b0183555b505050505056fea26469706673582212204c18d4a504a078fca73e2c1077682b64833c90d807d1ce81a44c14d72869897d64736f6c63430008130033", + "deployedBytecode": "608060405234801561001057600080fd5b50600436106100885760003560e01c8063cd5286d01161005b578063cd5286d0146100f2578063db9cc41014610132578063def60e0d14610145578063e24aa37c1461015857600080fd5b80631ae4eb681461008d5780635137b8a7146100b55780635e82d0a6146100ca578063bc548275146100df575b600080fd5b6100a061009b366004610850565b61016b565b60405190151581526020015b60405180910390f35b6100bd6101d5565b6040516100ac9190610892565b6100dd6100d8366004610850565b6102ae565b005b6100a06100ed366004610850565b610404565b610105610100366004610850565b610433565b6040805182516001600160a01b0316815260208084015115159082015291810151908201526060016100ac565b6100dd610140366004610924565b6104ab565b6100dd610153366004610850565b610606565b6100dd610166366004610850565b61064c565b60008060018484604051610180929190610970565b9081526040519081900360200190205460ff1690508061019f57600080fd5b600084846040516101b1929190610970565b9081526040519081900360200190205460ff600160a01b9091041691505092915050565b60606002805480602002602001604051908101604052809291908181526020016000905b828210156102a557838290600052602060002001805461021890610980565b80601f016020809104026020016040519081016040528092919081815260200182805461024490610980565b80156102915780601f1061026657610100808354040283529160200191610291565b820191906000526020600020905b81548152906001019060200180831161027457829003601f168201915b5050505050815260200190600101906101f9565b50505050905090565b6000600183836040516102c2929190610970565b9081526040519081900360200190205460ff169050806102e157600080fd5b6001600084846040516102f5929190610970565b9081526040519081900360200181208054921515600160a01b0260ff60a01b199093169290921790915561032c9084908490610970565b60405180910390207f9db172bd887aec98e834d86fb9ff0f1549ae602b8ca8ba1ee50902e4d502b9a060008585604051610367929190610970565b908152604051908190036020018120546001600160a01b0316906000906103919088908890610970565b9081526040519081900360200181205460ff600160a01b90910416906000906103bd9089908990610970565b908152604051908190036020018120600101546103f79392916001600160a01b039390931683529015156020830152604082015260600190565b60405180910390a2505050565b600060018383604051610418929190610970565b9081526040519081900360200190205460ff16905092915050565b604080516060810182526000808252602082018190529181019190915260008383604051610462929190610970565b908152604080516020928190038301812060608201835280546001600160a01b0381168352600160a01b900460ff16151593820193909352600190920154908201529392505050565b600081116104b857600080fd5b80600084846040516104cb929190610970565b90815260200160405180910390206001018190555033600084846040516104f3929190610970565b90815260405190819003602001812080546001600160a01b03939093166001600160a01b03199093169290921790915560009081906105359086908690610970565b9081526040519081900360200181208054921515600160a01b0260ff60a01b199093169290921790915560019061056f9085908590610970565b9081526040519081900360200190205460ff166105c557600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace016105c3838583610a1f565b505b60018084846040516105d8929190610970565b908152604051908190036020018120805492151560ff199093169290921790915561032c9084908490610970565b60006001838360405161061a929190610970565b9081526040519081900360200190205460ff1690508061063957600080fd5b60008084846040516102f5929190610970565b600060018383604051610660929190610970565b9081526040519081900360200190205460ff1690508061067f57600080fd5b6000808484604051610692929190610970565b9081526040519081900360200190205460ff600160a01b909104169050806106b957600080fd5b600084846040516106cb929190610970565b90815260405190819003602001812080546001600160a81b031916815560006001918201819055916107009087908790610970565b908152604051908190036020018120805492151560ff199093169290921790915561072e9085908590610970565b60405180910390207f9db172bd887aec98e834d86fb9ff0f1549ae602b8ca8ba1ee50902e4d502b9a060008686604051610769929190610970565b908152604051908190036020018120546001600160a01b0316906000906107939089908990610970565b9081526040519081900360200181205460ff600160a01b90910416906000906107bf908a908a90610970565b908152604051908190036020018120600101546107f99392916001600160a01b039390931683529015156020830152604082015260600190565b60405180910390a250505050565b60008083601f84011261081957600080fd5b50813567ffffffffffffffff81111561083157600080fd5b60208301915083602082850101111561084957600080fd5b9250929050565b6000806020838503121561086357600080fd5b823567ffffffffffffffff81111561087a57600080fd5b61088685828601610807565b90969095509350505050565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b8381101561091657888603603f1901855282518051808852835b818110156108ef578281018a01518982018b015289016108d4565b508781018901849052601f01601f19169096018701955093860193918601916001016108ba565b509398975050505050505050565b60008060006040848603121561093957600080fd5b833567ffffffffffffffff81111561095057600080fd5b61095c86828701610807565b909790965060209590950135949350505050565b8183823760009101908152919050565b600181811c9082168061099457607f821691505b6020821081036109b457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b601f821115610a1a57600081815260208120601f850160051c810160208610156109f75750805b601f850160051c820191505b81811015610a1657828155600101610a03565b5050505b505050565b67ffffffffffffffff831115610a3757610a376109ba565b610a4b83610a458354610980565b836109d0565b6000601f841160018114610a7f5760008515610a675750838201355b600019600387901b1c1916600186901b178355610ad9565b600083815260209020601f19861690835b82811015610ab05786850135825560209485019460019092019101610a90565b5086821015610acd5760001960f88860031b161c19848701351681555b505060018560011b0183555b505050505056fea26469706673582212204c18d4a504a078fca73e2c1077682b64833c90d807d1ce81a44c14d72869897d64736f6c63430008130033", + "sourceMap": "543:2046:0:-:0;;;;;;;;;;;;;;;;;;;", + "deployedSourceMap": "543:2046:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2267:231;;;;;;:::i;:::-;;:::i;:::-;;;948:14:1;;941:22;923:41;;911:2;896:18;2267:231:0;;;;;;;;2502:85;;;:::i;:::-;;;;;;;:::i;1253:229::-;;;;;;:::i;:::-;;:::i;:::-;;2162:101;;;;;;:::i;:::-;;:::i;1107:103::-;;;;;;:::i;:::-;;:::i;:::-;;;;2391:13:1;;-1:-1:-1;;;;;2387:39:1;2369:58;;2497:4;2485:17;;;2479:24;2472:32;2465:40;2443:20;;;2436:70;2550:17;;;2544:24;2522:20;;;2515:54;2357:2;2342:18;1107:103:0;2183:392:1;743:360:0;;;;;;:::i;:::-;;:::i;1527:232::-;;;;;;:::i;:::-;;:::i;1763:395::-;;;;;;:::i;:::-;;:::i;2267:231::-;2331:4;2345:11;2359;2371:2;;2359:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;2359:15:0;2382;;;;;;2476:6;2483:2;;2476:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:17;;-1:-1:-1;;;2476:17:0;;;;;-1:-1:-1;;2267:231:0;;;;:::o;2502:85::-;2550:15;2579:3;2572:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2502:85;:::o;1253:229::-;1307:11;1321;1333:2;;1321:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;1321:15:0;1344;;;;;;1388:4;1368:6;1375:2;;1368:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:24;;;;;-1:-1:-1;;;1368:24:0;-1:-1:-1;;;;1368:24:0;;;;;;;;;;1405:71;;1417:2;;;;1405:71;:::i;:::-;;;;;;;;;1421:6;1428:2;;1421:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:18;-1:-1:-1;;;;;1421:18:0;;;;1441:10;;1448:2;;;;1441:10;:::i;:::-;;;;;;;;;;;;;;:17;;-1:-1:-1;;;1441:17:0;;;;;;;1460:10;;1467:2;;;;1460:10;:::i;:::-;;;;;;;;;;;;;;:15;;;1405:71;;;;-1:-1:-1;;;;;3941:32:1;;;;3923:51;;4017:14;;4010:22;4005:2;3990:18;;3983:50;4064:2;4049:18;;4042:34;3911:2;3896:18;;3727:355;1405:71:0;;;;;;;;1299:183;1253:229;;:::o;2162:101::-;2222:4;2243:11;2255:2;;2243:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;2162:101:0;;;;:::o;1107:103::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;1195:6:0;1202:2;;1195:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;1188:17;;;;;;;-1:-1:-1;;;;;1188:17:0;;;;-1:-1:-1;;;1188:17:0;;;;;;;;;;;;;;;;;;;;;;1195:10;1107:103;-1:-1:-1;;;1107:103:0:o;743:360::-;822:1;817:4;:6;809:15;;;;;;849:4;832:6;839:2;;832:10;;;;;;;:::i;:::-;;;;;;;;;;;;;:15;;:21;;;;882:10;861:6;868:2;;861:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:31;;-1:-1:-1;;;;;861:31:0;;;;-1:-1:-1;;;;;;861:31:0;;;;;;;;;;:18;;;;900:10;;907:2;;;;900:10;:::i;:::-;;;;;;;;;;;;;;:25;;;;;-1:-1:-1;;;900:25:0;-1:-1:-1;;;;900:25:0;;;;;;;;;;-1:-1:-1;;938:15:0;;950:2;;;;938:15;:::i;:::-;;;;;;;;;;;;;;;;;933:52;;964:3;:12;;;;;;;-1:-1:-1;964:12:0;;;;;;;973:2;;964:12;;:::i;:::-;;933:52;1010:4;992:11;1004:2;;992:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;:22;;;;;-1:-1:-1;;992:22:0;;;;;;;;;;1027:71;;1039:2;;;;1027:71;:::i;1527:232::-;1583:11;1597;1609:2;;1597:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;1597:15:0;1620;;;;;;1664:5;1644:6;1651:2;;1644:10;;;;;;;:::i;1763:395::-;1819:11;1833;1845:2;;1833:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;1833:15:0;1856;;;;;;1943:18;1964:6;1971:2;;1964:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:17;;-1:-1:-1;;;1964:17:0;;;;;-1:-1:-1;1964:17:0;1989:22;;;;;;2027:6;2034:2;;2027:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;2020:17;;-1:-1:-1;;;;;;2020:17:0;;;2027:10;2020:17;;;;;;;2027:10;2045:15;;2057:2;;;;2045:15;:::i;:::-;;;;;;;;;;;;;;:23;;;;;-1:-1:-1;;2045:23:0;;;;;;;;;;2081:71;;2093:2;;;;2081:71;:::i;:::-;;;;;;;;;2097:6;2104:2;;2097:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:18;-1:-1:-1;;;;;2097:18:0;;;;2117:10;;2124:2;;;;2117:10;:::i;:::-;;;;;;;;;;;;;;:17;;-1:-1:-1;;;2117:17:0;;;;;;;2136:10;;2143:2;;;;2136:10;:::i;:::-;;;;;;;;;;;;;;:15;;;2081:71;;;;-1:-1:-1;;;;;3941:32:1;;;;3923:51;;4017:14;;4010:22;4005:2;3990:18;;3983:50;4064:2;4049:18;;4042:34;3911:2;3896:18;;3727:355;2081:71:0;;;;;;;;1811:347;;1763:395;;:::o;14:348:1:-;66:8;76:6;130:3;123:4;115:6;111:17;107:27;97:55;;148:1;145;138:12;97:55;-1:-1:-1;171:20:1;;214:18;203:30;;200:50;;;246:1;243;236:12;200:50;283:4;275:6;271:17;259:29;;335:3;328:4;319:6;311;307:19;303:30;300:39;297:59;;;352:1;349;342:12;297:59;14:348;;;;;:::o;367:411::-;438:6;446;499:2;487:9;478:7;474:23;470:32;467:52;;;515:1;512;505:12;467:52;555:9;542:23;588:18;580:6;577:30;574:50;;;620:1;617;610:12;574:50;659:59;710:7;701:6;690:9;686:22;659:59;:::i;:::-;737:8;;633:85;;-1:-1:-1;367:411:1;-1:-1:-1;;;;367:411:1:o;975:1203::-;1137:4;1166:2;1206;1195:9;1191:18;1236:2;1225:9;1218:21;1259:6;1294;1288:13;1325:6;1317;1310:22;1363:2;1352:9;1348:18;1341:25;;1425:2;1415:6;1412:1;1408:14;1397:9;1393:30;1389:39;1375:53;;1463:2;1455:6;1451:15;1484:1;1505;1515:634;1531:6;1526:3;1523:15;1515:634;;;1600:22;;;-1:-1:-1;;1596:36:1;1584:49;;1656:13;;1698:9;;1720:24;;;1768:1;1782:157;1798:8;1793:3;1790:17;1782:157;;;1906:12;;;1902:21;;1896:28;1873:16;;;1869:25;;1862:63;1817:12;;1782:157;;;-1:-1:-1;1963:21:1;;;1959:30;;1952:41;;;2059:2;2036:17;-1:-1:-1;;2032:31:1;2020:44;;;2016:53;;;-1:-1:-1;2127:12:1;;;;2092:15;;;;1557:1;1548:11;1515:634;;;-1:-1:-1;2166:6:1;;975:1203;-1:-1:-1;;;;;;;;975:1203:1:o;2580:479::-;2660:6;2668;2676;2729:2;2717:9;2708:7;2704:23;2700:32;2697:52;;;2745:1;2742;2735:12;2697:52;2785:9;2772:23;2818:18;2810:6;2807:30;2804:50;;;2850:1;2847;2840:12;2804:50;2889:59;2940:7;2931:6;2920:9;2916:22;2889:59;:::i;:::-;2967:8;;2863:85;;-1:-1:-1;3049:2:1;3034:18;;;;3021:32;;2580:479;-1:-1:-1;;;;2580:479:1:o;3064:273::-;3249:6;3241;3236:3;3223:33;3205:3;3275:16;;3300:13;;;3275:16;3064:273;-1:-1:-1;3064:273:1:o;3342:380::-;3421:1;3417:12;;;;3464;;;3485:61;;3539:4;3531:6;3527:17;3517:27;;3485:61;3592:2;3584:6;3581:14;3561:18;3558:38;3555:161;;3638:10;3633:3;3629:20;3626:1;3619:31;3673:4;3670:1;3663:15;3701:4;3698:1;3691:15;3555:161;;3342:380;;;:::o;4087:127::-;4148:10;4143:3;4139:20;4136:1;4129:31;4179:4;4176:1;4169:15;4203:4;4200:1;4193:15;4345:545;4447:2;4442:3;4439:11;4436:448;;;4483:1;4508:5;4504:2;4497:17;4553:4;4549:2;4539:19;4623:2;4611:10;4607:19;4604:1;4600:27;4594:4;4590:38;4659:4;4647:10;4644:20;4641:47;;;-1:-1:-1;4682:4:1;4641:47;4737:2;4732:3;4728:12;4725:1;4721:20;4715:4;4711:31;4701:41;;4792:82;4810:2;4803:5;4800:13;4792:82;;;4855:17;;;4836:1;4825:13;4792:82;;;4796:3;;;4436:448;4345:545;;;:::o;5066:1206::-;5190:18;5185:3;5182:27;5179:53;;;5212:18;;:::i;:::-;5241:94;5331:3;5291:38;5323:4;5317:11;5291:38;:::i;:::-;5285:4;5241:94;:::i;:::-;5361:1;5386:2;5381:3;5378:11;5403:1;5398:616;;;;6058:1;6075:3;6072:93;;;-1:-1:-1;6131:19:1;;;6118:33;6072:93;-1:-1:-1;;5023:1:1;5019:11;;;5015:24;5011:29;5001:40;5047:1;5043:11;;;4998:57;6178:78;;5371:895;;5398:616;4292:1;4285:14;;;4329:4;4316:18;;-1:-1:-1;;5434:17:1;;;5535:9;5557:229;5571:7;5568:1;5565:14;5557:229;;;5660:19;;;5647:33;5632:49;;5767:4;5752:20;;;;5720:1;5708:14;;;;5587:12;5557:229;;;5561:3;5814;5805:7;5802:16;5799:159;;;5938:1;5934:6;5928:3;5922;5919:1;5915:11;5911:21;5907:34;5903:39;5890:9;5885:3;5881:19;5868:33;5864:79;5856:6;5849:95;5799:159;;;6001:1;5995:3;5992:1;5988:11;5984:19;5978:4;5971:33;5371:895;;;5066:1206;;;:::o", + "sourcePath": "/workspaces/blockchain-integration-framework/packages/cactus-plugin-bungee/src/test/typescript/solidity/lock-asset-contract/lock-asset.sol", + "compiler": { + "name": "solc", + "version": "0.8.19+commit.7dd6d404" + }, + "ast": { + "absolutePath": "/workspaces/blockchain-integration-framework/packages/cactus-plugin-bungee/src/test/typescript/solidity/lock-asset-contract/lock-asset.sol", + "exportedSymbols": { + "Asset": [ + 8 + ], + "LockAsset": [ + 290 + ] + }, + "id": 291, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1, + "literals": [ + "solidity", + ">=", + "0.7", + ".0" + ], + "nodeType": "PragmaDirective", + "src": "413:24:0" + }, + { + "canonicalName": "Asset", + "id": 8, + "members": [ + { + "constant": false, + "id": 3, + "mutability": "mutable", + "name": "creator", + "nameLocation": "464:7:0", + "nodeType": "VariableDeclaration", + "scope": 8, + "src": "456:15:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "456:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 5, + "mutability": "mutable", + "name": "isLock", + "nameLocation": "482:6:0", + "nodeType": "VariableDeclaration", + "scope": 8, + "src": "477:11:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 4, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "477:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 7, + "mutability": "mutable", + "name": "size", + "nameLocation": "499:4:0", + "nodeType": "VariableDeclaration", + "scope": 8, + "src": "494:9:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 6, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "494:4:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "name": "Asset", + "nameLocation": "445:5:0", + "nodeType": "StructDefinition", + "scope": 291, + "src": "438:68:0", + "visibility": "public" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "LockAsset", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 290, + "linearizedBaseContracts": [ + 290 + ], + "name": "LockAsset", + "nameLocation": "552:9:0", + "nodeType": "ContractDefinition", + "nodes": [ + { + "constant": false, + "id": 13, + "mutability": "mutable", + "name": "assets", + "nameLocation": "592:6:0", + "nodeType": "VariableDeclaration", + "scope": 290, + "src": "566:32:0", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string => struct Asset)" + }, + "typeName": { + "id": 12, + "keyName": "", + "keyNameLocation": "-1:-1:-1", + "keyType": { + "id": 9, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "575:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "nodeType": "Mapping", + "src": "566:25:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string => struct Asset)" + }, + "valueName": "", + "valueNameLocation": "-1:-1:-1", + "valueType": { + "id": 11, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 10, + "name": "Asset", + "nameLocations": [ + "585:5:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 8, + "src": "585:5:0" + }, + "referencedDeclaration": 8, + "src": "585:5:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage_ptr", + "typeString": "struct Asset" + } + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 17, + "mutability": "mutable", + "name": "assetExists", + "nameLocation": "627:11:0", + "nodeType": "VariableDeclaration", + "scope": 290, + "src": "602:36:0", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_bool_$", + "typeString": "mapping(string => bool)" + }, + "typeName": { + "id": 16, + "keyName": "", + "keyNameLocation": "-1:-1:-1", + "keyType": { + "id": 14, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "611:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "nodeType": "Mapping", + "src": "602:24:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_bool_$", + "typeString": "mapping(string => bool)" + }, + "valueName": "", + "valueNameLocation": "-1:-1:-1", + "valueType": { + "id": 15, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "621:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 20, + "mutability": "mutable", + "name": "ids", + "nameLocation": "651:3:0", + "nodeType": "VariableDeclaration", + "scope": 290, + "src": "642:12:0", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_string_storage_$dyn_storage", + "typeString": "string[]" + }, + "typeName": { + "baseType": { + "id": 18, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "642:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "id": 19, + "nodeType": "ArrayTypeName", + "src": "642:8:0", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_string_storage_$dyn_storage_ptr", + "typeString": "string[]" + } + }, + "visibility": "internal" + }, + { + "anonymous": false, + "eventSelector": "9db172bd887aec98e834d86fb9ff0f1549ae602b8ca8ba1ee50902e4d502b9a0", + "id": 30, + "name": "Transaction", + "nameLocation": "667:11:0", + "nodeType": "EventDefinition", + "parameters": { + "id": 29, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 22, + "indexed": true, + "mutability": "mutable", + "name": "id", + "nameLocation": "694:2:0", + "nodeType": "VariableDeclaration", + "scope": 30, + "src": "679:17:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 21, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "679:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 24, + "indexed": false, + "mutability": "mutable", + "name": "creator", + "nameLocation": "706:7:0", + "nodeType": "VariableDeclaration", + "scope": 30, + "src": "698:15:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 23, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "698:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 26, + "indexed": false, + "mutability": "mutable", + "name": "isLock", + "nameLocation": "720:6:0", + "nodeType": "VariableDeclaration", + "scope": 30, + "src": "715:11:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 25, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "715:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 28, + "indexed": false, + "mutability": "mutable", + "name": "size", + "nameLocation": "733:4:0", + "nodeType": "VariableDeclaration", + "scope": 30, + "src": "728:9:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 27, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "728:4:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "678:60:0" + }, + "src": "661:78:0" + }, + { + "body": { + "id": 99, + "nodeType": "Block", + "src": "801:302:0", + "statements": [ + { + "expression": { + "arguments": [ + { + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 40, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "id": 38, + "name": "size", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34, + "src": "817:4:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": ">", + "rightExpression": { + "hexValue": "30", + "id": 39, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "822:1:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "817:6:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 37, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + 4294967278, + 4294967278 + ], + "referencedDeclaration": 4294967278, + "src": "809:7:0", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$returns$__$", + "typeString": "function (bool) pure" + } + }, + "id": 41, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "809:15:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 42, + "nodeType": "ExpressionStatement", + "src": "809:15:0" + }, + { + "expression": { + "id": 48, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "expression": { + "baseExpression": { + "id": 43, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "832:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 45, + "indexExpression": { + "id": 44, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32, + "src": "839:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "832:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 46, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberLocation": "843:4:0", + "memberName": "size", + "nodeType": "MemberAccess", + "referencedDeclaration": 7, + "src": "832:15:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "id": 47, + "name": "size", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 34, + "src": "849:4:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "832:21:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 49, + "nodeType": "ExpressionStatement", + "src": "832:21:0" + }, + { + "expression": { + "id": 56, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "expression": { + "baseExpression": { + "id": 50, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "861:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 52, + "indexExpression": { + "id": 51, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32, + "src": "868:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "861:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 53, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberLocation": "872:7:0", + "memberName": "creator", + "nodeType": "MemberAccess", + "referencedDeclaration": 3, + "src": "861:18:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "expression": { + "id": 54, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 4294967281, + "src": "882:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 55, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "886:6:0", + "memberName": "sender", + "nodeType": "MemberAccess", + "src": "882:10:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "861:31:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 57, + "nodeType": "ExpressionStatement", + "src": "861:31:0" + }, + { + "expression": { + "id": 63, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "expression": { + "baseExpression": { + "id": 58, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "900:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 60, + "indexExpression": { + "id": 59, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32, + "src": "907:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "900:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 61, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberLocation": "911:6:0", + "memberName": "isLock", + "nodeType": "MemberAccess", + "referencedDeclaration": 5, + "src": "900:17:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "hexValue": "66616c7365", + "id": 62, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "920:5:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "false" + }, + "src": "900:25:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 64, + "nodeType": "ExpressionStatement", + "src": "900:25:0" + }, + { + "condition": { + "id": 68, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "!", + "prefix": true, + "src": "937:16:0", + "subExpression": { + "baseExpression": { + "id": 65, + "name": "assetExists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 17, + "src": "938:11:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_bool_$", + "typeString": "mapping(string memory => bool)" + } + }, + "id": 67, + "indexExpression": { + "id": 66, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32, + "src": "950:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "938:15:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 76, + "nodeType": "IfStatement", + "src": "933:52:0", + "trueBody": { + "id": 75, + "nodeType": "Block", + "src": "954:31:0", + "statements": [ + { + "expression": { + "arguments": [ + { + "id": 72, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32, + "src": "973:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + ], + "expression": { + "id": 69, + "name": "ids", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 20, + "src": "964:3:0", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_string_storage_$dyn_storage", + "typeString": "string storage ref[] storage ref" + } + }, + "id": 71, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "968:4:0", + "memberName": "push", + "nodeType": "MemberAccess", + "src": "964:8:0", + "typeDescriptions": { + "typeIdentifier": "t_function_arraypush_nonpayable$_t_array$_t_string_storage_$dyn_storage_ptr_$_t_string_storage_$returns$__$attached_to$_t_array$_t_string_storage_$dyn_storage_ptr_$", + "typeString": "function (string storage ref[] storage pointer,string storage ref)" + } + }, + "id": 73, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "964:12:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 74, + "nodeType": "ExpressionStatement", + "src": "964:12:0" + } + ] + } + }, + { + "expression": { + "id": 81, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "baseExpression": { + "id": 77, + "name": "assetExists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 17, + "src": "992:11:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_bool_$", + "typeString": "mapping(string memory => bool)" + } + }, + "id": 79, + "indexExpression": { + "id": 78, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32, + "src": "1004:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "nodeType": "IndexAccess", + "src": "992:15:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "hexValue": "74727565", + "id": 80, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1010:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "true" + }, + "src": "992:22:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 82, + "nodeType": "ExpressionStatement", + "src": "992:22:0" + }, + { + "eventCall": { + "arguments": [ + { + "id": 84, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32, + "src": "1039:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + { + "expression": { + "baseExpression": { + "id": 85, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1043:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 87, + "indexExpression": { + "id": 86, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32, + "src": "1050:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1043:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 88, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1054:7:0", + "memberName": "creator", + "nodeType": "MemberAccess", + "referencedDeclaration": 3, + "src": "1043:18:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "expression": { + "baseExpression": { + "id": 89, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1063:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 91, + "indexExpression": { + "id": 90, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32, + "src": "1070:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1063:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 92, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1074:6:0", + "memberName": "isLock", + "nodeType": "MemberAccess", + "referencedDeclaration": 5, + "src": "1063:17:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "expression": { + "baseExpression": { + "id": 93, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1082:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 95, + "indexExpression": { + "id": 94, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 32, + "src": "1089:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1082:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 96, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1093:4:0", + "memberName": "size", + "nodeType": "MemberAccess", + "referencedDeclaration": 7, + "src": "1082:15:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 83, + "name": "Transaction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 30, + "src": "1027:11:0", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_string_memory_ptr_$_t_address_$_t_bool_$_t_uint256_$returns$__$", + "typeString": "function (string memory,address,bool,uint256)" + } + }, + "id": 97, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1027:71:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 98, + "nodeType": "EmitStatement", + "src": "1022:76:0" + } + ] + }, + "functionSelector": "db9cc410", + "id": 100, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "createAsset", + "nameLocation": "752:11:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 35, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 32, + "mutability": "mutable", + "name": "id", + "nameLocation": "780:2:0", + "nodeType": "VariableDeclaration", + "scope": 100, + "src": "764:18:0", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string" + }, + "typeName": { + "id": 31, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "764:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 34, + "mutability": "mutable", + "name": "size", + "nameLocation": "789:4:0", + "nodeType": "VariableDeclaration", + "scope": 100, + "src": "784:9:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 33, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "784:4:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "763:31:0" + }, + "returnParameters": { + "id": 36, + "nodeType": "ParameterList", + "parameters": [], + "src": "801:0:0" + }, + "scope": 290, + "src": "743:360:0", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 112, + "nodeType": "Block", + "src": "1180:30:0", + "statements": [ + { + "expression": { + "baseExpression": { + "id": 108, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1195:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 110, + "indexExpression": { + "id": 109, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 102, + "src": "1202:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1195:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "functionReturnParameters": 107, + "id": 111, + "nodeType": "Return", + "src": "1188:17:0" + } + ] + }, + "functionSelector": "cd5286d0", + "id": 113, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "getAsset", + "nameLocation": "1116:8:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 103, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 102, + "mutability": "mutable", + "name": "id", + "nameLocation": "1141:2:0", + "nodeType": "VariableDeclaration", + "scope": 113, + "src": "1125:18:0", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string" + }, + "typeName": { + "id": 101, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "1125:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "1124:20:0" + }, + "returnParameters": { + "id": 107, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 106, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 113, + "src": "1166:12:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_memory_ptr", + "typeString": "struct Asset" + }, + "typeName": { + "id": 105, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 104, + "name": "Asset", + "nameLocations": [ + "1166:5:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 8, + "src": "1166:5:0" + }, + "referencedDeclaration": 8, + "src": "1166:5:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage_ptr", + "typeString": "struct Asset" + } + }, + "visibility": "internal" + } + ], + "src": "1165:14:0" + }, + "scope": 290, + "src": "1107:103:0", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 151, + "nodeType": "Block", + "src": "1299:183:0", + "statements": [ + { + "assignments": [ + 119 + ], + "declarations": [ + { + "constant": false, + "id": 119, + "mutability": "mutable", + "name": "exists", + "nameLocation": "1312:6:0", + "nodeType": "VariableDeclaration", + "scope": 151, + "src": "1307:11:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 118, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "1307:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + } + ], + "id": 123, + "initialValue": { + "baseExpression": { + "id": 120, + "name": "assetExists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 17, + "src": "1321:11:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_bool_$", + "typeString": "mapping(string memory => bool)" + } + }, + "id": 122, + "indexExpression": { + "id": 121, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 115, + "src": "1333:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1321:15:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "1307:29:0" + }, + { + "expression": { + "arguments": [ + { + "id": 125, + "name": "exists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 119, + "src": "1352:6:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 124, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + 4294967278, + 4294967278 + ], + "referencedDeclaration": 4294967278, + "src": "1344:7:0", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$returns$__$", + "typeString": "function (bool) pure" + } + }, + "id": 126, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1344:15:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 127, + "nodeType": "ExpressionStatement", + "src": "1344:15:0" + }, + { + "expression": { + "id": 133, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "expression": { + "baseExpression": { + "id": 128, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1368:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 130, + "indexExpression": { + "id": 129, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 115, + "src": "1375:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1368:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 131, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberLocation": "1379:6:0", + "memberName": "isLock", + "nodeType": "MemberAccess", + "referencedDeclaration": 5, + "src": "1368:17:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "hexValue": "74727565", + "id": 132, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1388:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "true" + }, + "src": "1368:24:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 134, + "nodeType": "ExpressionStatement", + "src": "1368:24:0" + }, + { + "eventCall": { + "arguments": [ + { + "id": 136, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 115, + "src": "1417:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + { + "expression": { + "baseExpression": { + "id": 137, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1421:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 139, + "indexExpression": { + "id": 138, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 115, + "src": "1428:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1421:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 140, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1432:7:0", + "memberName": "creator", + "nodeType": "MemberAccess", + "referencedDeclaration": 3, + "src": "1421:18:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "expression": { + "baseExpression": { + "id": 141, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1441:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 143, + "indexExpression": { + "id": 142, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 115, + "src": "1448:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1441:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 144, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1452:6:0", + "memberName": "isLock", + "nodeType": "MemberAccess", + "referencedDeclaration": 5, + "src": "1441:17:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "expression": { + "baseExpression": { + "id": 145, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1460:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 147, + "indexExpression": { + "id": 146, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 115, + "src": "1467:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1460:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 148, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1471:4:0", + "memberName": "size", + "nodeType": "MemberAccess", + "referencedDeclaration": 7, + "src": "1460:15:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 135, + "name": "Transaction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 30, + "src": "1405:11:0", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_string_memory_ptr_$_t_address_$_t_bool_$_t_uint256_$returns$__$", + "typeString": "function (string memory,address,bool,uint256)" + } + }, + "id": 149, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1405:71:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 150, + "nodeType": "EmitStatement", + "src": "1400:76:0" + } + ] + }, + "functionSelector": "5e82d0a6", + "id": 152, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "lockAsset", + "nameLocation": "1262:9:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 116, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 115, + "mutability": "mutable", + "name": "id", + "nameLocation": "1288:2:0", + "nodeType": "VariableDeclaration", + "scope": 152, + "src": "1272:18:0", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string" + }, + "typeName": { + "id": 114, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "1272:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "1271:20:0" + }, + "returnParameters": { + "id": 117, + "nodeType": "ParameterList", + "parameters": [], + "src": "1299:0:0" + }, + "scope": 290, + "src": "1253:229:0", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 190, + "nodeType": "Block", + "src": "1575:184:0", + "statements": [ + { + "assignments": [ + 158 + ], + "declarations": [ + { + "constant": false, + "id": 158, + "mutability": "mutable", + "name": "exists", + "nameLocation": "1588:6:0", + "nodeType": "VariableDeclaration", + "scope": 190, + "src": "1583:11:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 157, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "1583:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + } + ], + "id": 162, + "initialValue": { + "baseExpression": { + "id": 159, + "name": "assetExists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 17, + "src": "1597:11:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_bool_$", + "typeString": "mapping(string memory => bool)" + } + }, + "id": 161, + "indexExpression": { + "id": 160, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "1609:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1597:15:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "1583:29:0" + }, + { + "expression": { + "arguments": [ + { + "id": 164, + "name": "exists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 158, + "src": "1628:6:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 163, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + 4294967278, + 4294967278 + ], + "referencedDeclaration": 4294967278, + "src": "1620:7:0", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$returns$__$", + "typeString": "function (bool) pure" + } + }, + "id": 165, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1620:15:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 166, + "nodeType": "ExpressionStatement", + "src": "1620:15:0" + }, + { + "expression": { + "id": 172, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "expression": { + "baseExpression": { + "id": 167, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1644:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 169, + "indexExpression": { + "id": 168, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "1651:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1644:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 170, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberLocation": "1655:6:0", + "memberName": "isLock", + "nodeType": "MemberAccess", + "referencedDeclaration": 5, + "src": "1644:17:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "hexValue": "66616c7365", + "id": 171, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1664:5:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "false" + }, + "src": "1644:25:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 173, + "nodeType": "ExpressionStatement", + "src": "1644:25:0" + }, + { + "eventCall": { + "arguments": [ + { + "id": 175, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "1694:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + { + "expression": { + "baseExpression": { + "id": 176, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1698:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 178, + "indexExpression": { + "id": 177, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "1705:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1698:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 179, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1709:7:0", + "memberName": "creator", + "nodeType": "MemberAccess", + "referencedDeclaration": 3, + "src": "1698:18:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "expression": { + "baseExpression": { + "id": 180, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1718:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 182, + "indexExpression": { + "id": 181, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "1725:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1718:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 183, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1729:6:0", + "memberName": "isLock", + "nodeType": "MemberAccess", + "referencedDeclaration": 5, + "src": "1718:17:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "expression": { + "baseExpression": { + "id": 184, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1737:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 186, + "indexExpression": { + "id": 185, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "1744:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1737:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 187, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1748:4:0", + "memberName": "size", + "nodeType": "MemberAccess", + "referencedDeclaration": 7, + "src": "1737:15:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 174, + "name": "Transaction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 30, + "src": "1682:11:0", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_string_memory_ptr_$_t_address_$_t_bool_$_t_uint256_$returns$__$", + "typeString": "function (string memory,address,bool,uint256)" + } + }, + "id": 188, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1682:71:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 189, + "nodeType": "EmitStatement", + "src": "1677:76:0" + } + ] + }, + "functionSelector": "def60e0d", + "id": 191, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "unLockAsset", + "nameLocation": "1536:11:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 155, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 154, + "mutability": "mutable", + "name": "id", + "nameLocation": "1564:2:0", + "nodeType": "VariableDeclaration", + "scope": 191, + "src": "1548:18:0", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string" + }, + "typeName": { + "id": 153, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "1548:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "1547:20:0" + }, + "returnParameters": { + "id": 156, + "nodeType": "ParameterList", + "parameters": [], + "src": "1575:0:0" + }, + "scope": 290, + "src": "1527:232:0", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 244, + "nodeType": "Block", + "src": "1811:347:0", + "statements": [ + { + "assignments": [ + 197 + ], + "declarations": [ + { + "constant": false, + "id": 197, + "mutability": "mutable", + "name": "exists", + "nameLocation": "1824:6:0", + "nodeType": "VariableDeclaration", + "scope": 244, + "src": "1819:11:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 196, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "1819:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + } + ], + "id": 201, + "initialValue": { + "baseExpression": { + "id": 198, + "name": "assetExists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 17, + "src": "1833:11:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_bool_$", + "typeString": "mapping(string memory => bool)" + } + }, + "id": 200, + "indexExpression": { + "id": 199, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 193, + "src": "1845:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1833:15:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "1819:29:0" + }, + { + "expression": { + "arguments": [ + { + "id": 203, + "name": "exists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 197, + "src": "1864:6:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 202, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + 4294967278, + 4294967278 + ], + "referencedDeclaration": 4294967278, + "src": "1856:7:0", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$returns$__$", + "typeString": "function (bool) pure" + } + }, + "id": 204, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1856:15:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 205, + "nodeType": "ExpressionStatement", + "src": "1856:15:0" + }, + { + "assignments": [ + 207 + ], + "declarations": [ + { + "constant": false, + "id": 207, + "mutability": "mutable", + "name": "assetIsLocked", + "nameLocation": "1948:13:0", + "nodeType": "VariableDeclaration", + "scope": 244, + "src": "1943:18:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 206, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "1943:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + } + ], + "id": 212, + "initialValue": { + "expression": { + "baseExpression": { + "id": 208, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "1964:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 210, + "indexExpression": { + "id": 209, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 193, + "src": "1971:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1964:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 211, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1975:6:0", + "memberName": "isLock", + "nodeType": "MemberAccess", + "referencedDeclaration": 5, + "src": "1964:17:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "1943:38:0" + }, + { + "expression": { + "arguments": [ + { + "id": 214, + "name": "assetIsLocked", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 207, + "src": "1997:13:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 213, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + 4294967278, + 4294967278 + ], + "referencedDeclaration": 4294967278, + "src": "1989:7:0", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$returns$__$", + "typeString": "function (bool) pure" + } + }, + "id": 215, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1989:22:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 216, + "nodeType": "ExpressionStatement", + "src": "1989:22:0" + }, + { + "expression": { + "id": 220, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "delete", + "prefix": true, + "src": "2020:17:0", + "subExpression": { + "baseExpression": { + "id": 217, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "2027:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 219, + "indexExpression": { + "id": 218, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 193, + "src": "2034:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "nodeType": "IndexAccess", + "src": "2027:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 221, + "nodeType": "ExpressionStatement", + "src": "2020:17:0" + }, + { + "expression": { + "id": 226, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "baseExpression": { + "id": 222, + "name": "assetExists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 17, + "src": "2045:11:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_bool_$", + "typeString": "mapping(string memory => bool)" + } + }, + "id": 224, + "indexExpression": { + "id": 223, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 193, + "src": "2057:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "nodeType": "IndexAccess", + "src": "2045:15:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "hexValue": "66616c7365", + "id": 225, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2063:5:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "false" + }, + "src": "2045:23:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 227, + "nodeType": "ExpressionStatement", + "src": "2045:23:0" + }, + { + "eventCall": { + "arguments": [ + { + "id": 229, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 193, + "src": "2093:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + { + "expression": { + "baseExpression": { + "id": 230, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "2097:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 232, + "indexExpression": { + "id": 231, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 193, + "src": "2104:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "2097:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 233, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "2108:7:0", + "memberName": "creator", + "nodeType": "MemberAccess", + "referencedDeclaration": 3, + "src": "2097:18:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "expression": { + "baseExpression": { + "id": 234, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "2117:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 236, + "indexExpression": { + "id": 235, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 193, + "src": "2124:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "2117:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 237, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "2128:6:0", + "memberName": "isLock", + "nodeType": "MemberAccess", + "referencedDeclaration": 5, + "src": "2117:17:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "expression": { + "baseExpression": { + "id": 238, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "2136:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 240, + "indexExpression": { + "id": 239, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 193, + "src": "2143:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "2136:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 241, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "2147:4:0", + "memberName": "size", + "nodeType": "MemberAccess", + "referencedDeclaration": 7, + "src": "2136:15:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 228, + "name": "Transaction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 30, + "src": "2081:11:0", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_string_memory_ptr_$_t_address_$_t_bool_$_t_uint256_$returns$__$", + "typeString": "function (string memory,address,bool,uint256)" + } + }, + "id": 242, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "2081:71:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 243, + "nodeType": "EmitStatement", + "src": "2076:76:0" + } + ] + }, + "functionSelector": "e24aa37c", + "id": 245, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "deleteAsset", + "nameLocation": "1772:11:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 194, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 193, + "mutability": "mutable", + "name": "id", + "nameLocation": "1800:2:0", + "nodeType": "VariableDeclaration", + "scope": 245, + "src": "1784:18:0", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string" + }, + "typeName": { + "id": 192, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "1784:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "1783:20:0" + }, + "returnParameters": { + "id": 195, + "nodeType": "ParameterList", + "parameters": [], + "src": "1811:0:0" + }, + "scope": 290, + "src": "1763:395:0", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 256, + "nodeType": "Block", + "src": "2228:35:0", + "statements": [ + { + "expression": { + "baseExpression": { + "id": 252, + "name": "assetExists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 17, + "src": "2243:11:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_bool_$", + "typeString": "mapping(string memory => bool)" + } + }, + "id": 254, + "indexExpression": { + "id": 253, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 247, + "src": "2255:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "2243:15:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "functionReturnParameters": 251, + "id": 255, + "nodeType": "Return", + "src": "2236:22:0" + } + ] + }, + "functionSelector": "bc548275", + "id": 257, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "isPresent", + "nameLocation": "2171:9:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 248, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 247, + "mutability": "mutable", + "name": "id", + "nameLocation": "2197:2:0", + "nodeType": "VariableDeclaration", + "scope": 257, + "src": "2181:18:0", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string" + }, + "typeName": { + "id": 246, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "2181:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "2180:20:0" + }, + "returnParameters": { + "id": 251, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 250, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 257, + "src": "2222:4:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 249, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "2222:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + } + ], + "src": "2221:6:0" + }, + "scope": 290, + "src": "2162:101:0", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 279, + "nodeType": "Block", + "src": "2337:161:0", + "statements": [ + { + "assignments": [ + 265 + ], + "declarations": [ + { + "constant": false, + "id": 265, + "mutability": "mutable", + "name": "exists", + "nameLocation": "2350:6:0", + "nodeType": "VariableDeclaration", + "scope": 279, + "src": "2345:11:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 264, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "2345:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + } + ], + "id": 269, + "initialValue": { + "baseExpression": { + "id": 266, + "name": "assetExists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 17, + "src": "2359:11:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_bool_$", + "typeString": "mapping(string memory => bool)" + } + }, + "id": 268, + "indexExpression": { + "id": 267, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 259, + "src": "2371:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "2359:15:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2345:29:0" + }, + { + "expression": { + "arguments": [ + { + "id": 271, + "name": "exists", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 265, + "src": "2390:6:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 270, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + 4294967278, + 4294967278 + ], + "referencedDeclaration": 4294967278, + "src": "2382:7:0", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$returns$__$", + "typeString": "function (bool) pure" + } + }, + "id": 272, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "2382:15:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 273, + "nodeType": "ExpressionStatement", + "src": "2382:15:0" + }, + { + "expression": { + "expression": { + "baseExpression": { + "id": 274, + "name": "assets", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 13, + "src": "2476:6:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_string_memory_ptr_$_t_struct$_Asset_$8_storage_$", + "typeString": "mapping(string memory => struct Asset storage ref)" + } + }, + "id": 276, + "indexExpression": { + "id": 275, + "name": "id", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 259, + "src": "2483:2:0", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string calldata" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "2476:10:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Asset_$8_storage", + "typeString": "struct Asset storage ref" + } + }, + "id": 277, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "2487:6:0", + "memberName": "isLock", + "nodeType": "MemberAccess", + "referencedDeclaration": 5, + "src": "2476:17:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "functionReturnParameters": 263, + "id": 278, + "nodeType": "Return", + "src": "2469:24:0" + } + ] + }, + "functionSelector": "1ae4eb68", + "id": 280, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "isAssetLocked", + "nameLocation": "2276:13:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 260, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 259, + "mutability": "mutable", + "name": "id", + "nameLocation": "2306:2:0", + "nodeType": "VariableDeclaration", + "scope": 280, + "src": "2290:18:0", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_string_calldata_ptr", + "typeString": "string" + }, + "typeName": { + "id": 258, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "2290:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "2289:20:0" + }, + "returnParameters": { + "id": 263, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 262, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 280, + "src": "2331:4:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 261, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "2331:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + } + ], + "src": "2330:6:0" + }, + "scope": 290, + "src": "2267:231:0", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 288, + "nodeType": "Block", + "src": "2566:21:0", + "statements": [ + { + "expression": { + "id": 286, + "name": "ids", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 20, + "src": "2579:3:0", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_string_storage_$dyn_storage", + "typeString": "string storage ref[] storage ref" + } + }, + "functionReturnParameters": 285, + "id": 287, + "nodeType": "Return", + "src": "2572:10:0" + } + ] + }, + "functionSelector": "5137b8a7", + "id": 289, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "getAllAssetsIDs", + "nameLocation": "2511:15:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 281, + "nodeType": "ParameterList", + "parameters": [], + "src": "2526:2:0" + }, + "returnParameters": { + "id": 285, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 284, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 289, + "src": "2550:15:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_string_memory_ptr_$dyn_memory_ptr", + "typeString": "string[]" + }, + "typeName": { + "baseType": { + "id": 282, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "2550:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "id": 283, + "nodeType": "ArrayTypeName", + "src": "2550:8:0", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_string_storage_$dyn_storage_ptr", + "typeString": "string[]" + } + }, + "visibility": "internal" + } + ], + "src": "2549:17:0" + }, + "scope": 290, + "src": "2502:85:0", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + } + ], + "scope": 291, + "src": "543:2046:0", + "usedErrors": [] + } + ], + "src": "413:2177:0" + }, + "functionHashes": { + "createAsset(string,uint256)": "db9cc410", + "deleteAsset(string)": "e24aa37c", + "getAllAssetsIDs()": "5137b8a7", + "getAsset(string)": "cd5286d0", + "isAssetLocked(string)": "1ae4eb68", + "isPresent(string)": "bc548275", + "lockAsset(string)": "5e82d0a6", + "unLockAsset(string)": "def60e0d" + }, + "gasEstimates": { + "creation": { + "codeDepositCost": "567600", + "executionCost": "600", + "totalCost": "568200" + }, + "external": { + "createAsset(string,uint256)": "infinite", + "deleteAsset(string)": "infinite", + "getAllAssetsIDs()": "infinite", + "getAsset(string)": "infinite", + "isAssetLocked(string)": "infinite", + "isPresent(string)": "infinite", + "lockAsset(string)": "infinite", + "unLockAsset(string)": "infinite" + } + } +} \ No newline at end of file diff --git a/packages/cactus-plugin-bungee/src/test/typescript/solidity/lock-asset-contract/lock-asset.sol b/packages/cactus-plugin-bungee/src/test/typescript/solidity/lock-asset-contract/lock-asset.sol new file mode 100644 index 00000000000..601d5a9e3e8 --- /dev/null +++ b/packages/cactus-plugin-bungee/src/test/typescript/solidity/lock-asset-contract/lock-asset.sol @@ -0,0 +1,87 @@ +// ***************************************************************************** +// IMPORTANT: If you update this code then make sure to recompile +// it and update the .json file as well so that they +// remain in sync for consistent test executions. +// With that said, there shouldn't be any reason to recompile this, like ever... +// ***************************************************************************** + +pragma solidity >=0.7.0; +struct Asset{ + address creator; + bool isLock; + uint size; +} +//TODO: DETEMINE CALLDATA VS MEMORY +contract LockAsset { + mapping (string => Asset) assets; + mapping (string => bool) assetExists; + string[] ids; + + event Transaction(string indexed id, address creator, bool isLock, uint size); + + function createAsset(string calldata id, uint size) public{ + require(size>0); + assets[id].size= size; + assets[id].creator = msg.sender; + assets[id].isLock = false; + if (!assetExists[id]){ + ids.push(id); + } + assetExists[id] = true; + emit Transaction(id, assets[id].creator, assets[id].isLock, assets[id].size); + } + + function getAsset(string calldata id) public view returns (Asset memory) { + return assets[id]; + } + + //Don't care if it is already locked + function lockAsset(string calldata id) public { + bool exists = assetExists[id]; + require(exists); + + assets[id].isLock = true; + emit Transaction(id, assets[id].creator, assets[id].isLock, assets[id].size); + + } + + //Don't care if it is already unlocked + function unLockAsset(string calldata id) public { + bool exists = assetExists[id]; + require(exists); + + assets[id].isLock = false; + emit Transaction(id, assets[id].creator, assets[id].isLock, assets[id].size); + + } + + function deleteAsset(string calldata id) public { + bool exists = assetExists[id]; + require(exists); + + //an asset could only be deleted if it is already locked + bool assetIsLocked = assets[id].isLock; + require(assetIsLocked); + + delete assets[id]; + assetExists[id] = false; + emit Transaction(id, assets[id].creator, assets[id].isLock, assets[id].size); + + } + + function isPresent(string calldata id) public view returns (bool) { + return assetExists[id]; + } + + function isAssetLocked(string calldata id) public view returns (bool) { + bool exists = assetExists[id]; + require(exists); + + //an asset could only be deleted if it is already locked + return assets[id].isLock; + } + + function getAllAssetsIDs() public view returns (string[] memory){ + return ids; + } +} diff --git a/yarn.lock b/yarn.lock index ec14fd124ba..51eb9f5ec66 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8450,10 +8450,16 @@ __metadata: "@types/tape": "npm:4.13.4" "@types/uuid": "npm:9.0.6" axios: "npm:1.6.0" + body-parser: "npm:1.20.2" express: "npm:4.18.2" fabric-network: "npm:2.2.20" + fs-extra: "npm:10.1.0" + key-encoder: "npm:2.0.3" + socket.io: "npm:4.5.4" typescript-optional: "npm:2.0.1" uuid: "npm:9.0.1" + web3: "npm:1.6.1" + web3-core: "npm:1.6.1" languageName: unknown linkType: soft