From 097a4cfd67858f9075349e3514b30341198a69f9 Mon Sep 17 00:00:00 2001 From: markspanbroek Date: Tue, 9 Aug 2022 06:29:06 +0200 Subject: [PATCH] Better command line options for Ethereum (#181) * [contracts] ContractInteractions.new() now requires account parameter * [cli] Only perform Ethereum interactions when --eth-account is specified * [cli] Add --persistence option that is disabled by default * [cli] Use Option for ethDeployment parameter * [node] Better error reporting when Ethereum node cannot be reached --- codex/codex.nim | 21 ++++++++++++++++----- codex/conf.nim | 14 ++++++++++---- codex/contracts/interactions.nim | 16 ++++++---------- codex/node.nim | 8 ++++++-- tests/codex/testnode.nim | 5 +---- tests/contracts/testInteractions.nim | 11 ++++++----- tests/testIntegration.nim | 2 ++ 7 files changed, 47 insertions(+), 30 deletions(-) diff --git a/codex/codex.nim b/codex/codex.nim index 50065883..23f30766 100644 --- a/codex/codex.nim +++ b/codex/codex.nim @@ -52,6 +52,21 @@ proc stop*(s: CodexServer) {.async.} = s.runHandle.complete() +proc new(_: type ContractInteractions, config: CodexConf): ?ContractInteractions = + if not config.persistence: + if config.ethAccount.isSome: + warn "Ethereum account was set, but persistence is not enabled" + return + + without account =? config.ethAccount: + error "Persistence enabled, but no Ethereum account was set" + quit QuitFailure + + if deployment =? config.ethDeployment: + ContractInteractions.new(config.ethProvider, account, deployment) + else: + ContractInteractions.new(config.ethProvider, account) + proc new*(T: type CodexServer, config: CodexConf): T = const SafePermissions = {UserRead, UserWrite} @@ -125,11 +140,7 @@ proc new*(T: type CodexServer, config: CodexConf): T = engine = BlockExcEngine.new(localStore, wallet, network, discovery, peerStore, pendingBlocks) store = NetworkStore.new(engine, localStore) erasure = Erasure.new(store, leoEncoderProvider, leoDecoderProvider) - contracts = ContractInteractions.new( - config.ethProvider, - config.ethDeployment, - config.ethAccount - ) + contracts = ContractInteractions.new(config) codexNode = CodexNodeRef.new(switch, store, engine, erasure, blockDiscovery, contracts) restServer = RestServerRef.new( codexNode.initRestApi(config), diff --git a/codex/conf.nim b/codex/conf.nim index 6f16adb2..da25a4d8 100644 --- a/codex/conf.nim +++ b/codex/conf.nim @@ -142,6 +142,12 @@ type name: "cache-size" abbr: "c" }: Natural + persistence* {. + desc: "Enables persistence mechanism, requires an Ethereum node" + defaultValue: false + name: "persistence" + .}: bool + ethProvider* {. desc: "The URL of the JSON-RPC API of the Ethereum node" defaultValue: "ws://localhost:8545" @@ -150,15 +156,15 @@ type ethAccount* {. desc: "The Ethereum account that is used for storage contracts" - defaultValue: EthAddress.default + defaultValue: EthAddress.none name: "eth-account" - .}: EthAddress + .}: Option[EthAddress] ethDeployment* {. desc: "The json file describing the contract deployment" - defaultValue: string.default + defaultValue: string.none name: "eth-deployment" - .}: string + .}: Option[string] of initNode: discard diff --git a/codex/contracts/interactions.nim b/codex/contracts/interactions.nim index a8c06f8e..711b4f9f 100644 --- a/codex/contracts/interactions.nim +++ b/codex/contracts/interactions.nim @@ -42,16 +42,11 @@ proc new*(_: type ContractInteractions, proc new*(_: type ContractInteractions, providerUrl: string, - deploymentFile: string = string.default, - account = Address.default): ?ContractInteractions = + account: Address, + deploymentFile: string = string.default): ?ContractInteractions = let provider = JsonRpcProvider.new(providerUrl) - - var signer: Signer - if account == Address.default: - signer = provider.getSigner() - else: - signer = provider.getSigner(account) + let signer = provider.getSigner(account) var deploy: Deployment try: @@ -65,8 +60,9 @@ proc new*(_: type ContractInteractions, ContractInteractions.new(signer, deploy) -proc new*(_: type ContractInteractions): ?ContractInteractions = - ContractInteractions.new("ws://localhost:8545") +proc new*(_: type ContractInteractions, + account: Address): ?ContractInteractions = + ContractInteractions.new("ws://localhost:8545", account) proc start*(interactions: ContractInteractions) {.async.} = await interactions.clock.start() diff --git a/codex/node.nim b/codex/node.nim index dba57555..39df9c5e 100644 --- a/codex/node.nim +++ b/codex/node.nim @@ -289,7 +289,7 @@ proc new*( engine: BlockExcEngine, erasure: Erasure, discovery: Discovery, - contracts: ?ContractInteractions): T = + contracts = ContractInteractions.none): T = T( switch: switch, blockStore: store, @@ -344,7 +344,11 @@ proc start*(node: CodexNodeRef) {.async.} = # TODO: generate proof return @[42'u8] - await contracts.start() + try: + await contracts.start() + except CatchableError as error: + error "Unable to start contract interactions: ", error=error.msg + node.contracts = ContractInteractions.none node.networkId = node.switch.peerInfo.peerId notice "Started codex node", id = $node.networkId, addrs = node.switch.peerInfo.addrs diff --git a/tests/codex/testnode.nim b/tests/codex/testnode.nim index 88b7a3b6..4d0c35af 100644 --- a/tests/codex/testnode.nim +++ b/tests/codex/testnode.nim @@ -17,7 +17,6 @@ import pkg/codex/node import pkg/codex/manifest import pkg/codex/discovery import pkg/codex/blocktype as bt -import pkg/codex/contracts import ./helpers @@ -39,7 +38,6 @@ suite "Test Node": peerStore: PeerCtxStore pendingBlocks: PendingBlocksManager discovery: DiscoveryEngine - contracts: ?ContractInteractions setup: file = open(path.splitFile().dir /../ "fixtures" / "test.jpg") @@ -54,8 +52,7 @@ suite "Test Node": discovery = DiscoveryEngine.new(localStore, peerStore, network, blockDiscovery, pendingBlocks) engine = BlockExcEngine.new(localStore, wallet, network, discovery, peerStore, pendingBlocks) store = NetworkStore.new(engine, localStore) - contracts = ContractInteractions.new() - node = CodexNodeRef.new(switch, store, engine, nil, blockDiscovery, contracts) # TODO: pass `Erasure` + node = CodexNodeRef.new(switch, store, engine, nil, blockDiscovery) # TODO: pass `Erasure` await node.start() diff --git a/tests/contracts/testInteractions.nim b/tests/contracts/testInteractions.nim index fbfbd0fe..30ea896b 100644 --- a/tests/contracts/testInteractions.nim +++ b/tests/contracts/testInteractions.nim @@ -5,23 +5,24 @@ import ./examples ethersuite "Storage Contract Interactions": + let account = Address.example + var contracts: ContractInteractions setup: - contracts = !ContractInteractions.new() + contracts = !ContractInteractions.new(account) test "can be instantiated with a signer and deployment info": let signer = provider.getSigner() let deployment = deployment() check ContractInteractions.new(signer, deployment).isSome - test "can be instantiated with a provider url and account": + test "can be instantiated with a provider url": let url = "http://localhost:8545" let account = Address.example let deployment = "vendor" / "dagger-contracts" / "deployment-localhost.json" - check ContractInteractions.new(url).isSome - check ContractInteractions.new(url, account = account).isSome - check ContractInteractions.new(url, deploymentFile = deployment).isSome + check ContractInteractions.new(url, account).isSome + check ContractInteractions.new(url, account, deployment).isSome test "provides purchasing": check contracts.purchasing != nil diff --git a/tests/testIntegration.nim b/tests/testIntegration.nim index 621bebb0..6af170c5 100644 --- a/tests/testIntegration.nim +++ b/tests/testIntegration.nim @@ -20,11 +20,13 @@ ethersuite "Integration tests": node1 = startNode [ "--api-port=8080", "--udp-port=8090", + "--persistence", "--eth-account=" & $accounts[0] ] node2 = startNode [ "--api-port=8081", "--udp-port=8091", + "--persistence", "--eth-account=" & $accounts[1] ] baseurl1 = "http://localhost:8080/api/codex/v1"