From 7502b9ad2c5460a97d169d2afc13300b9fed808a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Uhl=C3=AD=C5=99?= Date: Mon, 9 Jun 2025 12:04:15 +0200 Subject: [PATCH] feat(cirdl): auto-discovery of marketplace contract (#1259) --- codex/codex.nim | 2 +- codex/contracts/deployment.nim | 12 +++++--- tests/contracts/testDeployment.nim | 25 +++------------- tools/cirdl/cirdl.nim | 47 ++++++++++++++++++++++-------- 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/codex/codex.nim b/codex/codex.nim index a887dd4c..ef5a3b94 100644 --- a/codex/codex.nim +++ b/codex/codex.nim @@ -105,7 +105,7 @@ proc bootstrapInteractions(s: CodexServer): Future[void] {.async.} = quit QuitFailure signer = wallet - let deploy = Deployment.new(provider, config) + let deploy = Deployment.new(provider, config.marketplaceAddress) without marketplaceAddress =? await deploy.address(Marketplace): error "No Marketplace address was specified or there is no known address for the current network" quit QuitFailure diff --git a/codex/contracts/deployment.nim b/codex/contracts/deployment.nim index 7613e6fd..84c845ce 100644 --- a/codex/contracts/deployment.nim +++ b/codex/contracts/deployment.nim @@ -9,7 +9,7 @@ import ./marketplace type Deployment* = ref object provider: Provider - config: CodexConf + marketplaceAddressOverride: ?Address const knownAddresses = { # Hardhat localhost network @@ -32,12 +32,16 @@ proc getKnownAddress(T: type, chainId: UInt256): ?Address = return knownAddresses[id].getOrDefault($T, Address.none) -proc new*(_: type Deployment, provider: Provider, config: CodexConf): Deployment = - Deployment(provider: provider, config: config) +proc new*( + _: type Deployment, + provider: Provider, + marketplaceAddressOverride: ?Address = none Address, +): Deployment = + Deployment(provider: provider, marketplaceAddressOverride: marketplaceAddressOverride) proc address*(deployment: Deployment, contract: type): Future[?Address] {.async.} = when contract is Marketplace: - if address =? deployment.config.marketplaceAddress: + if address =? deployment.marketplaceAddressOverride: return some address let chainId = await deployment.provider.getChainId() diff --git a/tests/contracts/testDeployment.nim b/tests/contracts/testDeployment.nim index 86a5fe00..e8983437 100644 --- a/tests/contracts/testDeployment.nim +++ b/tests/contracts/testDeployment.nim @@ -1,8 +1,7 @@ import pkg/ethers +import pkg/questionable import codex/contracts/deployment -import codex/conf import codex/contracts -import pkg/codex/utils/natutils import ../asynctest import ../checktest @@ -15,28 +14,12 @@ method getChainId*( ): Future[UInt256] {.async: (raises: [ProviderError, CancelledError]).} = return provider.chainId -proc configFactory(): CodexConf = - CodexConf( - cmd: StartUpCmd.persistence, - nat: NatConfig(hasExtIp: false, nat: NatNone), - metricsAddress: parseIpAddress("127.0.0.1"), - ) - -proc configFactory(marketplace: Option[EthAddress]): CodexConf = - CodexConf( - cmd: StartUpCmd.persistence, - nat: NatConfig(hasExtIp: false, nat: NatNone), - metricsAddress: parseIpAddress("127.0.0.1"), - marketplaceAddress: marketplace, - ) - asyncchecksuite "Deployment": let provider = MockProvider() test "uses conf value as priority": let deployment = Deployment.new( - provider, - configFactory(EthAddress.init("0x59b670e9fA9D0A427751Af201D676719a970aaaa")), + provider, some !Address.init("0x59b670e9fA9D0A427751Af201D676719a970aaaa") ) provider.chainId = 1.u256 @@ -45,7 +28,7 @@ asyncchecksuite "Deployment": check $(!address) == "0x59b670e9fa9d0a427751af201d676719a970aaaa" test "uses chainId hardcoded values as fallback": - let deployment = Deployment.new(provider, configFactory()) + let deployment = Deployment.new(provider) provider.chainId = 167005.u256 let address = await deployment.address(Marketplace) @@ -53,7 +36,7 @@ asyncchecksuite "Deployment": check $(!address) == "0x948cf9291b77bd7ad84781b9047129addf1b894f" test "return none for unknown networks": - let deployment = Deployment.new(provider, configFactory()) + let deployment = Deployment.new(provider) provider.chainId = 1.u256 let address = await deployment.address(Marketplace) diff --git a/tools/cirdl/cirdl.nim b/tools/cirdl/cirdl.nim index 11051672..19a94de4 100644 --- a/tools/cirdl/cirdl.nim +++ b/tools/cirdl/cirdl.nim @@ -8,6 +8,7 @@ import pkg/questionable/results import pkg/zippy/tarballs import pkg/chronos/apps/http/httpclient import ../../codex/contracts/marketplace +import ../../codex/contracts/deployment proc consoleLog(logLevel: LogLevel, msg: LogOutputStr) {.gcsafe.} = try: @@ -16,24 +17,31 @@ proc consoleLog(logLevel: LogLevel, msg: LogOutputStr) {.gcsafe.} = except IOError as err: logLoggingFailure(cstring(msg), err) -proc noOutput(logLevel: LogLevel, msg: LogOutputStr) = discard +proc noOutput(logLevel: LogLevel, msg: LogOutputStr) = + discard defaultChroniclesStream.outputs[0].writer = consoleLog defaultChroniclesStream.outputs[1].writer = noOutput defaultChroniclesStream.outputs[2].writer = noOutput proc printHelp() = - info "Usage: ./cirdl [circuitPath] [rpcEndpoint] [marketplaceAddress]" + info "Usage: ./cirdl [circuitPath] [rpcEndpoint] ([marketplaceAddress])" info " circuitPath: path where circuit files will be placed." info " rpcEndpoint: URL of web3 RPC endpoint." - info " marketplaceAddress: Address of deployed Codex marketplace contracts." + info " marketplaceAddress: Address of deployed Codex marketplace contracts. If left out, will auto-discover based on connected network." -proc getCircuitHash(rpcEndpoint: string, marketplaceAddress: string): Future[?!string] {.async.} = - let provider = JsonRpcProvider.new(rpcEndpoint) - without address =? Address.init(marketplaceAddress): - return failure("Invalid address: " & marketplaceAddress) +proc getMarketplaceAddress( + provider: JsonRpcProvider, mpAddressOverride: ?Address +): Future[?Address] {.async.} = + let deployment = Deployment.new(provider, mpAddressOverride) + let address = await deployment.address(Marketplace) - let marketplace = Marketplace.new(address, provider) + return address + +proc getCircuitHash( + provider: JsonRpcProvider, marketplaceAddress: Address +): Future[?!string] {.async.} = + let marketplace = Marketplace.new(marketplaceAddress, provider) let config = await marketplace.configuration() return success config.proofs.zkeyHash @@ -77,23 +85,38 @@ proc copyFiles(unpackDir: string, circuitPath: string): ?!void = proc main() {.async.} = info "Codex Circuit Downloader, Aww yeah!" let args = os.commandLineParams() - if args.len != 3: + if args.len < 2 or args.len > 3: printHelp() return let circuitPath = args[0] rpcEndpoint = args[1] - marketplaceAddress = args[2] zipfile = "circuit.tar.gz" unpackFolder = "." / "tempunpackfolder" - debug "Starting", circuitPath, rpcEndpoint, marketplaceAddress + var mpAddressOverride: ?Address + + if args.len == 3: + without parsed =? Address.init(args[2]): + raise newException(ValueError, "Invalid ethereum address") + mpAddressOverride = some parsed + + debug "Starting", circuitPath, rpcEndpoint if (dirExists(unpackFolder)): removeDir(unpackFolder) - without circuitHash =? (await getCircuitHash(rpcEndpoint, marketplaceAddress)), err: + let provider = JsonRpcProvider.new(rpcEndpoint) + + without marketplaceAddress =? + (await getMarketplaceAddress(provider, mpAddressOverride)), err: + error "No known marketplace address, nor any specified manually", msg = err.msg + return + + info "Marketplace address", address = $marketplaceAddress + + without circuitHash =? (await getCircuitHash(provider, marketplaceAddress)), err: error "Failed to get circuit hash", msg = err.msg return debug "Got circuithash", circuitHash