UNPKG

@kadena/hardhat-chainweb

Version:
154 lines 6.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ChainwebNetwork = void 0; const ethers_1 = require("ethers"); const chainweb_graph_js_1 = require("./chainweb-graph.js"); const sleep_js_1 = require("./sleep.js"); const ethers_helpers_js_1 = require("./ethers-helpers.js"); const logger_js_1 = require("./logger.js"); const chain_js_1 = require("./chain.js"); const hardhat_ethers_provider_js_1 = require("@nomicfoundation/hardhat-ethers/internal/hardhat-ethers-provider.js"); const pure_utils_js_1 = require("../pure-utils.js"); class ChainwebNetwork { constructor(config) { this.config = config; this.logger = { info: (msg) => (0, logger_js_1.logInfo)('reset', '-', msg), error: (msg) => (0, logger_js_1.logError)('reset', '-', msg), }; this.chains = makeChainweb(this.logger, this.config); this.graph = config.chainweb.graph; } getProvider(cid) { const chain = this.chains[cid]; if (chain === undefined) { throw new Error(`Chain not found in Chainweb ${cid}`); } const provider = chain.provider; if (provider === null) { throw new Error(`Chain network is not running ${cid}`); } return provider; } async start() { try { this.logger.info('Starting chain networks'); await Promise.all(Object.values(this.chains).map((chain) => { return chain.start(); })); this.logger.info('Chainweb chains initialized'); } catch (e) { this.logger.error(`Failure while starting networks: ${e}, ${e.stack}`); await this.stop(); } } async stop() { this.logger.info('Stopping chain networks'); await Promise.all(Object.values(this.chains).map((chain) => chain.stop())); this.logger.info('Stopped chain networks'); } // Mock getProof: // // Call our chainweb SPV api with the necesasry proof parameters. // // This mocks the call of the follwing API: // // http://localhost:1848/chainweb/0.0/evm-development/chain/${trgChain}/spv/chain/${origin.chain}/height/${origin.height}/transaction/${origin.txIdx}/event/${origin.eventIdx} // async getSpvProof(trgChain, origin) { // get origin chain const provider = new hardhat_ethers_provider_js_1.HardhatEthersProvider(this.getProvider(Number(origin.chain)), `${(0, pure_utils_js_1.getNetworkStem)(this.config.chainwebName)}${origin.chain}`); // Query Event information from origin chain const blockLogs = await provider.getLogs({ fromBlock: origin.height, toBlock: origin.height, }); const txLogs = blockLogs.filter((l) => BigInt(l.transactionIndex) === origin.txIdx); const log = txLogs[Number(origin.eventIdx)]; if (log === undefined || log.removed) { new Error('No log entry found at origin'); } const topics = log.topics; if (topics.length != 4) { throw new Error(`Expected exactly four topics at origin, but got ${topics.length}`); } // for target chain to advance enough blocks such that the origin information // is available. // // TODO should fail at least once so that the caller has to wait? // const src = this.chains[Number(origin.chain)]; const trg = this.chains[trgChain]; if (src === undefined || trg === undefined) { throw new Error(`Chain not found in Chainweb`); } const dist = BigInt((0, chainweb_graph_js_1.distance)(src.cid, trg.cid, this.graph)); let trgHeight = BigInt(await trg.getBlockNumber()); while (trgHeight < origin.height + dist) { console.log(`waiting for SPV proof to become available on chain ${trgChain}; current height ${trgHeight}; required height ${origin.height + dist}`); await trg.mineRequest(); (0, sleep_js_1.sleep)(100); trgHeight = BigInt(await trg.getBlockNumber()); } const coder = ethers_1.ethers.AbiCoder.defaultAbiCoder(); // FIXME: double check the event signature // (uint32,address,uint64,uint64,uint64) const xorigin = Object.values({ chainId: origin.chain, address: log.address, height: origin.height, txIdx: origin.txIdx, eventIdx: origin.eventIdx, }); // (uint32,address,uint64,(uint32,address,uint64,uint64,uint64)) const xmsg = Object.values({ trgChainId: ethers_1.ethers.toNumber(topics[1]), trgAddress: (0, ethers_helpers_js_1.wordToAddress)(topics[2]), opType: ethers_1.ethers.toNumber(topics[3]), data: coder.decode(['bytes'], log.data)[0], origin: xorigin, }); const params = 'tuple(uint32,address,uint64,bytes,tuple(uint32,address,uint64,uint64,uint64))'; const payload = coder.encode([params], [xmsg]); const hash = ethers_1.ethers.keccak256(payload); return ethers_1.ethers.concat([hash, payload]); } } exports.ChainwebNetwork = ChainwebNetwork; /* *************************************************************************** */ /* Chainweb Network */ function makeChainweb(logger, config) { var _a; const graph = config.chainweb.graph; const networks = config.networks; // Create Individual Chains logger.info('creating chains'); const chains = {}; for (const networkName in networks) { if (networkName.includes((0, pure_utils_js_1.getNetworkStem)(config.chainwebName))) { const networkConfig = networks[networkName]; if ((_a = config.overrideForking) === null || _a === void 0 ? void 0 : _a.url) { networkConfig.forking = { enabled: true, ...config.overrideForking }; } chains[networkConfig.chainwebChainId] = new chain_js_1.Chain(networkConfig, config.chainweb.logging); } } // Put Chains into the Chainweb Graph logger.info('integrating chains into Chainweb'); for (const c in chains) { if (graph[c] === undefined) { console.log(c, graph); throw new Error(`Missing configuration for chain ${c}`); } chains[c].adjacents = graph[c].map((x) => { const a = chains[x]; if (a === undefined) { throw new Error(`Missing configuration for chain ${x}`); } return chains[x]; }); } return chains; } //# sourceMappingURL=chainweb.js.map