feat(cirdl): auto-discovery of marketplace contract (#1259)

This commit is contained in:
Adam Uhlíř 2025-06-09 12:04:15 +02:00 committed by GitHub
parent 3e17207a0b
commit 7502b9ad2c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 48 additions and 38 deletions

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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